0

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

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

我有一个列表[节点]:
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,但他们没有我需要的示例。

4

2 回答 2

1

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

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.

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

于 2013-04-17T15:11:34.007 回答
1

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

它比设置更便宜、更容易CometActor,但只有在用户提出问题时才能得到结果。因此,这种方式服务器将无法自行将一些更新推送到浏览器。

于 2013-04-17T16:12:58.410 回答