【问题标题】:Lift - CRUD with Designer Friendly templates and AjaxLift - 具有设计师友好模板和 Ajax 的 CRUD
【发布时间】:2013-08-31 18:04:52
【问题描述】:

在 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>

还有一个sn-p

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 sn-p 很简单 - 我们修改现有标记并将我们的列表呈现为表格行。

我有点犹豫要不要完成create sn-p。保留列表项的代码很简单,但我不知道如何处理用新的&lt;tr&gt; 更新&lt;table&gt; 的部分。我想避免用标记污染 sn-p 为设计师留下空间来处理他们想要的表格。你会如何完成这个 sn-p?

【问题讨论】:

    标签: ajax scala templates lift


    【解决方案1】:

    这样的方法怎么样?:

    在类中,添加一个字段private var html: NodeSeq = NodeSeq.Empty

    将渲染方法更改为 def render(in: NodeSeq) = {html = in; ...; cssTransform.apply(in)}

    create,再次重用html。类似JsAppend("id", transformation.apply(html))

    我知道的替代方案:

    • SHtml.memoize(可能很有用,试试看)
    • &lt;tr&gt; 列创建单独的html-s。在代码中你可以使用def html: NodeSeq = Templates("myHtmlFile" :: Nil).openOr(NodeSeq.Empty)。对我来说似乎很脏,因为 &lt;tr&gt; 代码将与 &lt;table&gt; 分开。

    【讨论】:

      【解决方案2】:

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

      为此,我们会给 table 一个 ID,例如:

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

      然后在你的 sn-p 中,你可以这样做:

      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)
        }
      }
      

      只要发生第一次渲染并设置RequestVar,任何对tableMemo.get.foreach{ _.setHtml } 的调用都会重新渲染表格。

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

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

      首先,使用给定行的 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)
        }
      

      注意:上面的第一个&lt;tr&gt;会绑定到你html中的T​​R,第二个会绑定到模板中指定的TR。

      定义创建 = { 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-01-11
        • 1970-01-01
        • 1970-01-01
        • 2011-03-27
        • 2021-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多