我有一个关于服务器端数据网格控件的design
基本问题implementation
(类似于 asp.net GridView)。
我已经创建了 dummyDataGrid.scala.html
但我可以用更复杂和更实用(使用函数式编程)的方式编写。
@(ID: String, List: Seq[model.admin.Partner.Partner], Columns: Seq[String])(content: Html= Html(""))
@import model.admin.Partner.Partner
<table>
<thead>
<tr>
@for(j <- Columns) {
<td>@j</td>
}
</tr>
</thead>
@for(i <- List) {
<tr> @for(j <- Columns) {
<td> @code.classes.EntityFactory.getValue[Partner](i, j)</td>
}
</tr>
}
</table>
基本上我有一个用于表头的循环和第二个用于通过反射获取价值的双循环。
object EntityFactory {
def getValue[T](entity: T,fieldName: String)(implicit ev: scala.reflect.ClassTag[T]) = {
entity.getClass.getMethods.find(_.getName == fieldName).get.invoke(entity)
}
}
在我看来,我像这样使用这个 Datagrid:
@DataGrid(ID = "partners", List = Partners, Columns = Seq("ID","Name", "ShortName")){
}
我希望拥有的
我想要这样的东西:
@DataGrid(ID = "partners", List = Partners){
@LinkColumn(ID = "url", Propety = "ID",Url = controllers.admin.routes.PartnerController.read(""))
@LabelColumn(ID = "Name", Property="Name", CssClass="Some")
@LabelColumn(ID = "Email",Property="Email", CssClass="Some")
@DateDateColumn(ID = "ActiveFrom")
}
在这里,我为此创建了结构
在某些专栏中,我想做一些技巧来Url
从Property
. 像这样的东西:
@(ID: String,entity: Partner, Property: String, Url: String)
@import model.admin.Partner.Partner
<div>
here I want to inject code.classes.EntityFactory.getValue[Partner](entity,"ID")
into @Url
</div>
<a href="@Url(code.classes.EntityFactory.getValue[Partner](entity,Property))">klik</a>
感谢阅读和帮助。
编辑
一段时间后,我终于自己找到了答案。此代码分为两个区域:code
和view
。
代码
以下是描述列类型的特征或类。
trait Column {
val ID: String
val Label: Option[String]
val Header: String
val Property: String
val AlternateProperty: Option[String]
val Visible: Boolean
val Enabled: Boolean
}
object Column {}
case class LinkColumn(ID: String,
Label: Option[String] = None,
Header: String,
Property: String,
AlternateProperty: Option[String] = None,
Visible: Boolean = true,
Enabled: Boolean = true,
Url: Any => Call,
Type: String = LinkColumnType.Action
) extends Column {}
case class LabelColumn(ID: String,
Label: Option[String] = None,
Header: String,
Property: String,
AlternateProperty: Option[String] = None,
Visible: Boolean = true,
Enabled: Boolean = true) extends Column {}
case class MergedActionColumn(ID: String,
Label: Option[String] = None,
Header: String,
Property: String,
AlternateProperty: Option[String] = None,
Visible: Boolean = true,
Enabled: Boolean = true,
Actions: Seq[LinkColumn]) extends Column {}
object LinkColumnType extends Enumeration {
type Type = Value
val Link = ""
val Action = "btn btn-success"
}
还有一些助手代码。
object EntityFactory {
def getField(entity: Any,fieldName: String) = {
entity.getClass.getMethods.find(_.getName == fieldName).get.invoke(entity)
}
}
意见
DataGrid.scala.html
@(ID: String, List: Seq[Any], CssClass: String = "",
ShowCreateButton: Boolean = true)(Columns: Seq[Any])(implicit request: play.api.mvc.RequestHeader, lang: play.api.i18n.Lang)
@import code.classes.{EntityFactory => ef}
@import code.views.tags.DataGrid.{LabelColumn, LinkColumn, Column, MergedActionColumn}
@import views.html.tags.controls.DataGrid.{LabelColumn => vLabelColumn, LinkColumn => vLinkColumn}
@import code.views.tags.DataGrid.LinkColumnType
@import code.Ext
@if(ShowCreateButton){
<a class="btn btn-success" href="@controllers.admin.routes.PartnerController.create()">
<i class="icon-zoom-in icon-white"></i>
@Ext.te("common.add", lang.code)
</a>
}
<table class="@CssClass">
<thead>
<tr>
@for(j <- Columns) {
@j match {
case s: MergedActionColumn =>{
<td>@s.Header</td>
}
case s: Column => {
<td>@s.Header</td>
}
case _ => {}
}
}
</tr>
</thead>
@for(l <- List) {
<tr>
@for(c <- Columns) {
@c match {
case s: LabelColumn => {
@vLabelColumn(ID = s.ID, Header = s.Header, Property = s.Property,
Visible = s.Visible)(entity = l)
}
case s: LinkColumn => {
@vLinkColumn(ID = s.ID, Label = s.Label, Header = s.Header, Property = s.Property,
AlternateProperty = s.AlternateProperty, Visible = s.Visible, Enabled = s.Enabled,
Url = s.Url, Type = LinkColumnType.Link
)(entity = l)
}
case s: MergedActionColumn => {
<td> <table> <tr>
@for(s <- s.Actions) {
@vLinkColumn(ID = s.ID, Label = s.Label, Header = s.Header, Property = s.Property,
AlternateProperty = s.AlternateProperty, Visible = s.Visible, Enabled = s.Enabled,
Url = s.Url, Type = LinkColumnType.Action, CssClass = "no-border no-bg"
)(entity = l)
}
</tr>
</table>
</td>
}
}
}
</tr>
}
</table>
LinkColumn.scala.html
@( ID: String,
Label: Option[String] = None,
Header: String,
Property: String,
AlternateProperty: Option[String] = None,
Visible: Boolean = true,
Enabled: Boolean = true,
Url: String => Call,
Type: String = code.views.tags.DataGrid.LinkColumnType.Action,
CssClass: String = "")(implicit entity: Any)
@import code.classes.{EntityFactory => ef}
<td class="@CssClass">
<a href="@Url(ef.getField(entity, Property).toString)" class="@Type">
@Label.getOrElse(ef.getField(entity, AlternateProperty getOrElse Property).toString)
</a>
</td>
LabelColumn.scala.html
@(ID: String,
Label: Option[String] = None,
Header: String,
Property: String,
AlternateProperty: Option[String] = None,
Visible: Boolean = true,
Enabled: Boolean = true)(implicit entity: Any)
@import code.classes.{EntityFactory => ef}
<td>
@ef.getField(entity, Property)
</td>
数据网格的使用:
@DataGrid(ID = "facilities", List = Facilities, CssClass = "table table-striped table-bordered bootstrap-datatable datatable",
ShowCreateButton = true)(
Seq(
LabelColumn(ID = "ID", Header = "ID", Property = "ID"),
LabelColumn(ID = "Name", Header = "Nazwa", Property = "Name"),
MergedActionColumn(ID = "Actions", Header = "Actions", Property = "ID", Actions = Seq(
LinkColumn(ID = "Update", Header = "ID", Property = "ID", Url = pfc.update, Label = Some("Update")),
LinkColumn(ID = "Delete", Header = "ID", Property = "ID", Url = pc.delete, Label = Some("Delete")),
LinkColumn(ID = "Delete", Header = "ID", Property = "ID", Url = pc.read, Label = Some("View")),
LinkColumn(ID = "Delete", Header = "ID", Property = "ID", Url = pfc.index, Label = Some("Facilities"))
))
)
)
当然,这只是基本的 scaldfolding,但它展示了如何使用 playframework 视图,如 asp.net 或 jsf 中的控件。