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
Listing:
/wiring.html
<!-- The Invoice Area --> <div> <div id="invoice_lines" data-lift="InvoiceWiring.showLines">input goes here</div> <div> <button data-lift="InvoiceWiring.addLine?div=invoice_lines">Add</button> </div> <div>Subtotal: <span data-lift="InvoiceWiring.subtotal">subtotal</span></div> <div>Tax Rate: <input data-lift="InvoiceWiring.taxRate"></div> <div>Taxable: <span data-lift="InvoiceWiring.taxable">taxable</span></div> <div>Tax: <span data-lift="InvoiceWiring.tax">Tax</span></div> <div>Total: <span data-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.