将Scala绑定到Lift中的HTML

时间:2013-04-17 14:37:04

标签: binding lift

我开始玩Lift了。我想创建一个基本应用程序,它通过输入字段从用户获取输入,对该输入执行数据库搜索,并获取该数据库搜索的结果并创建一个对象列表,然后它绑定到某些HTML代码。

我只需要帮助绑定部分,但首先需要一些背景信息。

我有一个List [Node]:
case class Node(aname:String, adata:String) {..}

我有这个html绑定到:

<div class="lift:helloWorld.displayNodes">
    <div>
            <div><li><B>Node:</B></li></div>
                <div>Name: <node:name></node:name></div>
                <div>Data: <node:data></node:data></div>
                <BR>
        </div>
</div>

问题是这段代码从代码段调用我的方法displayNodes并传入其中。这样我可以绑定它,因为我有html代码。所以我这样绑定:

//this method is called from the index.html and 
def displayNodes(html : NodeSeq) : NodeSeq = {
    nodeList.flatMap {node => Helpers.bind("node", html, "name"->node.name, "data"->node.data) }
}

现在问题:
如何绑定而不在html中指定我希望html代码调用哪个方法。我的意思是我想删除这一行:<div class="lift:helloWorld.displayNodes">因为我不希望在填充列表之前调用它。所以基本上代替html“调用”scala代码我希望scala代码调用html并绑定到它,但只有在它有数据之后。怎么办呢?

PS - 我看了cookbook.liftweb.net,但他们没有我需要的例子。

2 个答案:

答案 0 :(得分:1)

我不确定你是如何设置系统的,但通常对于服务器推送你想要使用Comet actor。下面的代码应该让您在该路径上开始,因为它将执行初始渲染,然后允许您根据消息事件向页面发送部分更新。因此,在这种情况下,它将响应加载列表时应发送的事件pushList。您可以阅读有关演员here的更多信息。

HTML文件

<div data-lift="comet?type=HelloWorldActor">
   <span id="nodes"></span> 
</div>

<强>演员

case class HelloWorldActor() extends CometActor {
  //Handle any messages received
  override def lowPriority: PartialFunction[Any, Unit] = {
    case "pushList" => 
      partialUpdate {
        JsCmds.SetHtml("nodes", displayNodes.apply(listTemplate))
      }
  }

  //Look up the template from templates-hidden/list.html or if that does not exist
  //use the default NodeSeq specified
  def listTemplate = Templates.apply("templates-hidden" :: "list" :: Nil) openOr
    <div>
       <div><li><B>Node:</B></li></div>
       <div>Name: <span name="name"></span></div>
       <div>Data: <span name="data"></span></div>
       <BR>
    </div>

  //Load the list, and then on completion send the actor the message to push the list
  //This could also happen from outside the actor, you'd send the message in a similar 
  //fashion from wherever it happens
  def loadList() = {
    //load the data in your list and on complete
    this ! "pushList"
  }

  //The CSS Selector to output the node
  def displayNodes = {
    "*" #> nodeList.map { node =>
      "@name" #> node.name &
      "@data" #> node.data
    }
  }

  //Initial CSS Transformation
  override def render = {
    //Your initial CSS transformation
  }
}

您将看到JsCmds.SetHtml是实际在页面上设置HTML的内容。它只是一个JavaScript命令,用于在html元素上查找给定的id,然后将其替换为指定的NodeSeq。如果您不想使用Comet,可以使用该命令作为任何返回JsCmd的Lift组件的响应。

我还提取了输出节点的HTML,以便于说明。 Templates对象包含一个使用设计器友好模板的机制,可以查找和重复使用,这样你就不会丢失任何东西。但是,如果您想在一个文件中继续使用HTML,则可以捕获初始render中的元素:"#nodes" #> { ns => listTemplate = ns; PassThru }(将listTemplate更改为{{1}后当然)。

答案 1 :(得分:1)

我建议使用SHtml.idMemoize http://lift.la/blog/shtmlidmemoize-simple-ajax-updating 这样,您最初可以拥有一个输入页面,但没有结果。在用户输入数据并且服务器获取数据库数据后,您可以通过查询outer.setHtml

来更新结果

它比设置CometActor更便宜,更容易,但只有当用户提出要求时才会得到结果。因此,这样服务器就无法自行将某些更新推送到浏览器。