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

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.

主站蜘蛛池模板: 渝中区| 双鸭山市| 山阳县| 南澳县| 吐鲁番市| 闻喜县| 仁怀市| 霍州市| 皋兰县| 郧西县| 大同市| 余江县| 九江县| 临颍县| 永平县| 定南县| 安仁县| 平顺县| 天祝| 曲阳县| 宜良县| 梁山县| 广河县| 桂平市| 浮梁县| 台江县| 邮箱| 东港市| 茂名市| 招远市| 财经| 通化市| 澄迈县| 即墨市| 康保县| 万盛区| 新巴尔虎右旗| 灌南县| 石渠县| 英山县| 华池县|