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

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.

主站蜘蛛池模板: 班玛县| 来凤县| 东阿县| 固镇县| 巴东县| 越西县| 浦县| 沙雅县| 化隆| 本溪| 天镇县| 延边| 松原市| 四平市| 扎囊县| 龙海市| 万山特区| 青海省| 万荣县| 丹棱县| 高台县| 富蕴县| 宁都县| 南漳县| 廉江市| 延边| 城口县| 资溪县| 蕉岭县| 宣威市| 五台县| 丁青县| 夏邑县| 汕头市| 江川县| 家居| 汉阴县| 灵山县| 宣武区| 杭锦旗| 剑川县|