Seven Things


As web pages get more complex, there are a lot of interdependent items displayed on the page. For example, you may have a list of invitations along with a count of invitations. As you accept or reject each invitation (assuming this is done via Ajax), you want the invation count to be automatically updated. Lift's Wiring allows you to declare relationships among the various elements on a page and when any of the precedent elements change, the dependent items are redisplayed on the next HTTP response (Ajax or Comet).

Those are a lot of words. Let's see how we can build an invoice screen
Subtotal: subtotal
Tax Rate:
Taxable: taxable
Tax: Tax
Total: Total
Let's take a look at the markup for the invoice
Listing: /wiring.html
      <!-- The Invoice Area -->
      <div>
        <div id="invoice_lines" class="lift:InvoiceWiring.showLines">input goes here</div>
        <div>
          <button class="lift:InvoiceWiring.addLine?div=invoice_lines">Add</button>
        </div>

        <div>Subtotal: <span class="lift:InvoiceWiring.subtotal">subtotal</span></div>

        <div>Tax Rate: <input class="lift:InvoiceWiring.taxRate"></div>

        <div>Taxable: <span class="lift:InvoiceWiring.taxable">taxable</span></div>

        <div>Tax: <span class="lift:InvoiceWiring.tax">Tax</span></div>

        <div>Total: <span class="lift:InvoiceWiring.total">Total</span></div>
      </div>
Each of the items on the screen that need to be automatically updates is declared as a snippet. And the snippet implementation for each wired element is simple as well:
Listing: /net/liftweb/seventhings/snippet/InvoiceWiring.scala
  def subtotal = WiringUI.toNode(Info.subtotal)(doubleDraw)

  /**
   * Wire an element to taxable
   */
  def taxable = WiringUI.toNode(Info.taxable)(doubleDraw)

  def tax = WiringUI.toNode(Info.tax, JqWiringSupport.fade)(doubleDraw)

  def total = WiringUI.toNode(Info.total, JqWiringSupport.fade)(doubleDraw)

Finally, we declare the relationship among the elements (or cells in Wiring-speak):
Listing: /net/liftweb/seventhings/snippet/InvoiceWiring.scala
  private object Info {
    val invoices = ValueCell(List(newLine))
    val taxRate = ValueCell(0.05d)
    val subtotal = invoices.lift(_.foldLeft(0d)(_ + _.price))
    val taxable = invoices.lift(_.filter(_.taxable).
                                foldLeft(0D)(_ + _.price))

    val tax = taxRate.lift(taxable) {_ * _}

    val total = subtotal.lift(tax) {_ + _}    
  }

Using Wiring, you can create very complex inter-relationships with the elements on the screen. When one is updated, all the dependent elements update automatically. This is a tremendous time-saver and makes maintaining your site much easier because the maintainer doesn't have to know all the dependencies.

Lift is Copyright 2007-2011 WorldWide Conferencing, LLC. Distributed under an Apache 2.0 License.