0

什么是在 Lift 中实现简单 CRUD 接口并实现它的干净方法

  1. 设计师友好
  2. 阿贾克斯

假设我们有一个视图

<table data-lift="CrudList">
    <tr>
         <td role="data">Item goes here</td>
         <td><button role="remove" type="button">remove</button></td>
    </tr>
    <tr class="clearable">
         <td>Item two here</td>
         <td><button type="button">remove</button></td>
    </tr>
    <tr class="clearable">
         <td>Item three!</td>
         <td><button type="button">remove</button></td>
    </tr>
</table>
<form data-lift="form.ajax">
    <div data-lift="CrudList.create">
        <input type="text" name="text"></input>
        <button type="submit"></button>
    </div>
</form>

还有一个片段

object CrudList {
  def render = {
    def remove(item: String) = () => {
      ListDAO.remove(item)
      JE.JsRaw("""Some JavaScript to remove <tr> from the UI""")
    }

    ClearClearable &
    "tr *" #> ListDAO.all.map(item => {
      "role=data" #> item &
      "role=remove" #> ajaxInvoke(remove(item))
    })
  }

  def create = {
    var text = ""

    def process(): JsCmd = {
      val item = ListDAO.create(text)
      JsCmds.Noop // TODO: replace this with some JsCmd 
                  // that will create and populate new table row in the UI
                  // without polluting the snippet with markup
    }

    "@text" #> SHtml.text(text, s => text = s) &
    "button *+" #> SHtml.hidden(process)
  }
}

示例可能有错误,纯粹用于演示。

render片段很简单——我们修改现有标记并将我们的列表呈现为表格行。

我有点犹豫要不要完成这个create片段。保留列表项的代码很简单,但我不知道如何处理<table>使用 new更新的部分<tr>。我想避免用标记污染片段,为设计师留下空间来处理他们想要的表格。你将如何完成这个片段?

4

2 回答 2

1

How about an approach like this?:

in the class, add a field private var html: NodeSeq = NodeSeq.Empty

change the render method to def render(in: NodeSeq) = {html = in; ...; cssTransform.apply(in)}

in create, reuse the html again. Something like JsAppend("id", transformation.apply(html)).

Alternatives I know about:

  • SHtml.memoize (might be very useful, try it)
  • create separate html-s for <tr> columns. In the code you may use def html: NodeSeq = Templates("myHtmlFile" :: Nil).openOr(NodeSeq.Empty). Seems dirty to me because the <tr> code would be separated from the <table> then.
于 2013-08-28T17:01:14.883 回答
1

最简单的方法就是换掉整个 HTML 表格。为此,您可以使用内置函数SHtml来记忆初始转换。

为此,我们将提供table一个 ID,如下所示:

<table data-lift="CrudList" id="mytable">

然后在您的代码段中,您可以执行以下操作:

object CrudList {
  object tableMemo extends RequestVar[Box[IdMemoizeTransform]](Empty)

  def render = {
    def remove(item: String) = () => {
      ListDAO.remove(item)
      tableMemo.get.foreach{ _.setHtml }
    }

    "#mytable" #> SHtml.idMemoize{ memo =>
      tableMemo(memo)
      ClearClearable &
      "tr *" #> ListDAO.all.map(item => {
        "role=data" #> item &
        "role=remove" #> ajaxInvoke(remove(item))
      })
    }
  }

  def create = {
    var text = ""

    def process(): JsCmd = {
      val item = ListDAO.create(text)
      tableMemo.get.foreach{ _.setHtml }
    }

    "@text" #> SHtml.text(text, s => text = s) &
    "button *+" #> SHtml.hidden(process)
  }
}

如果tableMemo.get.foreach{ _.setHtml }第一次渲染发生并设置RequestVar.

如果您只想重新渲染受影响的行,那将更具挑战性。

我可能会尝试这样的事情:

首先,使用给定行的 HTML 创建一个模板。在本例中,我们将其放入templates-hidden/rowtemplate.html. 随着内容:

<tr>
     <td role="data">Item goes here</td>
     <td><button role="remove" type="button">remove</button></td>
</tr>

然后,我们将修改渲染以提供每个 tr 并从模板中检索行

  val rowTemplate = Templates("templates-hidden" :: "rowtemplate" :: Nil) openOr <tr></tr>

  def render = {
    def remove(item: String) = () => {
      ListDAO.remove(item)
      JsCmds.Run("$('#' + item.id).remove()")
    }

    ClearClearable &
    "tr" #> {
      "tr" #> ListDAO.all.map(item => {
        "* [id]" #> item.id &
        "role=data" #> item &
        "role=remove" #> ajaxInvoke(remove(item))
      })
    }.apply(rowTemplate)
  }

注意:<tr>上面的第一个将绑定到您的 html 中的 TR,第二个将绑定到模板中指定的 TR。

def 创建 = { var text = ""

 def process(): JsCmd = {
   val item = ListDAO.create(text)
   val rowNS = {
        "* [id]" #> item.id &
        "role=data" #> item &
        "role=remove" #> ajaxInvoke(remove(item))
    }.apply(rowTemplate)
   JsCmds.Run("tr:last").append(rowNS.toString)
 }

 "@text" #> SHtml.text(text, s => text = s) &
 "button *+" #> SHtml.hidden(process)
}

我尚未对其进行测试以确保一切正常,但希望能为您指明正确的方向。

于 2013-08-28T17:03:58.613 回答