官术网_书友最值得收藏!

Nesting snippets

Snippets are lazily evaluated, which means that the Inner snippet will not be invoked until the Outer snippet is evaluated. By using this neat feature, we can nest snippet invocations in our HTML templates, and thus gain a powerful tool to dynamically generate HTML with a fine-grained control. For example, you can use this feature to show different things to your users depending on whether they are logged in or not and on their authorization level. We'll learn how to do this in this recipe.

Getting ready

Create a new project and add the following designer-friendly HTML code into the index.html file to invoke the snippet and trigger all of the mechanisms to render snippets recursively:

<div data-lift="Outer.choose">
  <div class="inner-div"></div>
</div>

How to do it...

Nesting snippets can be done by following these steps:

  1. Create a file called Outer.scala in the snippet package with the following content:
    import net.liftweb.util.Helpers._
    import net.liftweb.http.S
    import net.liftweb.util.BasicTypesHelpers._
    import net.liftweb.common.Full
    
    object Outer {
      def choose = {
        val loggedIn = S.param("loggedin").flatMap(asBoolean) 
        loggedIn match {
          case Full(b) if b => ".inner-div [class+]" #> "lift:Inner.logged"
          case _ => ".inner-div [class+]" #> "lift:Inner.nonlogged"
        }
      }
    }

    After building the Outer snippet, we'll build the Inner one.

  2. Create a file called Inner.scala in the snippet package with the following content:
    import net.liftweb.util.Helpers._
    
    object Inner {
      def logged = {
        "div *" #> "Should only be visible when user is logged in"
      }
      
      def nonlogged = {
        "div *" #> "Should only be visible when user is not logged in"
      }
    }
  3. Access the following URLs to test this example:
    • http://localhost:8080?loggedin=true
    • http://localhost:8080?loggedin=false
    • http://localhost:8080

    You will see the following output, as shown in the following screenshot:

How it works...

As you can see, the only snippet invocation in the HTML file is the invocation of the Outer snippet; the rest of the HTML is just plain HTML markup—nothing special or new. But we have two snippets and only one invocation in the HTML file. As it turns out, when Lift starts to process HTML, it will find the snippet invocation and will pass the HTML code to it.

The Outer snippet will check for the presence of the loggedin parameter. It does this by using the param method of the S object; it then uses this parameter to choose which snippet will be rendered next.

Note

S is an object that holds the HTTP requests/responses and HTTP session state.

When we invoke the S object's param method, it will try to get a query string—having the key passed as parameter to the param method—from the URL.

The S.param method returns Box[String]; it will return Full[String] if it successfully gets the query string, or Empty if the key doesn't exist.

Box is a container class that can be empty or full. If Box contains a value different from null, the box's value is Full(value); otherwise, the value of Box will be Empty. Other possible values for an empty box are Failure and ParamFailure, which can include the reason why the box is empty.

If the parameter is true, it will append lift:Inner.logged to the class attribute of the div tag with inner-div as value of the class attribute; if the parameter is false or non-existent, it will append lift:Inner.nonlogged to the class attribute.

Note

How does Lift know that we want to append something to the class attribute of a tag? By using the [attr+] selector, we tell Lift to append the result of the right-hand side of the #> operator to the tag attribute. Since we used [class+], we told Lift to append lift:... to the class attribute.

You can read more about CSS Selector Transforms at http://simply.liftweb.net/index-7.10.html.

Once the Outer snippet finishes its job, the transformed HTML—if the value of the loggedin parameter is true—will look like the following code:

<div>
  <div class="inner l:Inner.logged"></div>
</div>

We no longer have the invocation of the Outer snippet. The HTML will now invoke the Inner snippet, which is a snippet that will render some text inside the div tag. The final HTML will look the following code:

<div>
  <div class="inner">
    Should only be visible when user is logged in
  </div>
</div>

What we did is:

  1. Invoke the Outer snippet.
  2. Choose which snippet should be called, based on some condition.
  3. Return HTML that contains in itself an invocation to another snippet—the Inner snippet.
  4. Process the HTML in the Inner snippet.
  5. Return the transformed HTML.

That's all you need to create nested calls to snippets in Lift.

主站蜘蛛池模板: 阿尔山市| 阆中市| 广德县| 墨玉县| 浪卡子县| 怀仁县| 五台县| 偏关县| 长子县| 黄浦区| 上栗县| 福州市| 温泉县| 阳泉市| 威远县| 正阳县| 七台河市| 江西省| 成安县| 丁青县| 周宁县| 墨玉县| 柳州市| 宜黄县| 枣庄市| 鄂托克前旗| 会泽县| 本溪市| 大足县| 高平市| 德化县| 张掖市| 淮滨县| 丰顺县| 高阳县| 淮南市| 潜江市| 通化县| 格尔木市| 海丰县| 红河县|