在Lift中实现简单的CRUD接口并使其成为
的简洁方法假设我们有一个观点
<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>
更新<tr>
的部分。我想避免使用标记来污染代码段,为设计人员留下他们想要的表格空间。你会如何完成这个片段?
答案 0 :(得分: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
(可能非常有用,请尝试一下)<tr>
列创建单独的html-s。在代码中,您可以使用def html: NodeSeq = Templates("myHtmlFile" :: Nil).openOr(NodeSeq.Empty)
。对我来说似乎很脏,因为<tr>
代码会与<table>
分开。答案 1 :(得分: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 create = { 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)
}
我没有对此进行测试,以确保一切正常,但希望能指出正确的方向。