Knockout Grid - 扩展版






4.93/5 (9投票s)
本文介绍了如何使用 knockout 示例中使用的 simplegrid,我为其添加了接受列模板以与外部 DOM 绑定进行交互的功能,以及时尚简洁的分页器和多选选项。
引言
首先,让我们谈谈在 knockout 示例中看到的 knockoutgrid。它是一个简单的 grid,接受 columns 和 data,以表格形式展示您的数据。对于不需要 grid 与外部 DOM 交互的需求来说,它是完美的。但有时也会有这样的需求,例如,grid 显示学生列表,需求是当我点击每个学生某列时,我需要查看该学生的成绩,如下所示:
因此,通过使用自定义模板,您可以将 grid 列模板的点击事件绑定到外部 DOM 元素进行交互。
背景
要理解 grid 的功能,我建议您在 knockout 的 示例中练习 knockoutgrid。
Knockout grid 提供以下配置选项。
this.gridViewModel = new ko.simpleGrid.viewModel({
data: this.items,
columns: [
{ headerText: "Item Name", rowText: "name" },
{ headerText: "Sales Count", rowText: "sales" },
{ headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } }
],
pageSize: 4
});
1) data - 实体集合。
2) columns - 表格的标题文本,rowText 是您集合中的属性名称。
3) pageSize - 指定每页应包含多少行。
使用代码
接下来谈谈我的代码。我修改了 knockout grid 并添加了几个字段来接受列模板、全选模板和 ViewModel 属性,以便将您所有的 grid 业务逻辑放在其中,这样您就可以与外部 DOM 绑定进行交互,以满足您的业务需求。
我利用了 knockout 模板绑定的优势来满足 grid 的需求。您可以 这里 了解更多关于模板绑定的信息。
以下是我为满足 grid 需求而添加的字段。
1) columnTemplate - 它接受一个字符串,即脚本 ID,您将在其中拥有行的标记。
2) ViewModel - 在这里存储您的所有业务逻辑,以与 grid 列进行交互,例如点击事件,如我上面所示,以打开一个弹出模态框来查看特定学生的成绩。
3) hasMultiSelect - 这是一个布尔字段,如果指定。您必须在列模板标记中添加一个带复选框的 <td>,以便您可以将其绑定到您自己的 ViewModel 属性。您还必须指定全选模板,如下文所述。
4) headerMultiselectTemplate - 这是一个字符串字段,接受用于 header multiselect <th> 的脚本 ID,以便您可以将其绑定到您自己的 ViewModel 属性,从而可以在选择或取消选择行时执行自定义或预处理/后处理工作。
5) addEnabled - 这是一个布尔字段,当您需要一个添加模板位于开头以在 grid 中添加新条目时使用。您需要指定 add template 来使用此功能。
6) addTemplate - 这是一个字符串字段,接受用于指定自定义添加行的模板的脚本 ID,您可以拥有任何 HTML,如下拉列表、文本输入框,并将属性绑定到您自己的 ViewModel 属性。
如果您不使用上述任何字段,grid 将回退到 knockout 的简单 grid 样式,仅进行简单的文本绑定,并显示我自定义分页的简单 grid,如下所示。
使用简单 grid 的代码
this.simpleStudentGrid = new ko.simpleGrid.viewModel({
data: this.studentModel.students,
pageSize: 10,
columns: [{ headerText: "Roll No", rowText: "srNo" }, { headerText: "Name", rowText: "name" }],
});
并将其属性绑定到您的 DOM。
示例 1: (使用列模板查看学生成绩)
要使用列属性,您需要 have columnTemplate 和 ViewModel 来处理点击事件以查看成绩,这将弹出一个 bootstrap 模态框窗口。
Grid 绑定:
this.gridWithColumnTemplate = new ko.simpleGrid.viewModel({
data: this.studentModel.students,
pageSize: 10,
columnTemplate: "gridWithColumnTemplate",
columns: [{ headerText: "Roll No", rowText: "" }, { headerText: "Name", rowText: "" }, { headerText: "View Marks", rowText: "" }],
ViewModel: studentModel
});
ViewModel : (ViewModel studentModel 的一个属性,如上面配置中所指定)
self.ViewMarks = function (data, e) {
e.stopPropagation();
self.name(data.name);
self.srNo(data.srNo);
self.marks(data.marks);
showTopModal("studentModal");
};
模板
<script id="gridWithColumnTemplate" type="text/html">
<td data-bind="text: srNo"></td>
<td data-bind="text: name"></td>
<td><a href="#" data-bind="click: $parent.ViewModel.ViewMarks">View marks</a></td>
</script>
输出:
当您点击“查看成绩”时,一个 bootstrap 弹出模态框会打开,显示该特定学生的成绩。
您可以在模板中使用任何 HTML 输入元素,例如一个移除 glyphicon,点击它将移除特定用户,在您的 ViewModel 中拥有移除业务逻辑。
示例 2: (使用列模板移除用户 )
Grid 绑定与上面相同,除了 columnTemplate 更改。
View Model : (移除用户属性)
self.RemoveStudent = function (data, e) {
e.stopPropagation();
alert("All grids are bind to same data source, Are you sure you want to delete data.");
self.students.remove(data);
};
模板
<script id="gridRemoveStudent" type="text/html">
<td data-bind="text: srNo"></td>
<td data-bind="text: name"></td>
<td><a href="#" data-bind="click: $parent.ViewModel.RemoveStudent"><i class="glyphicon windows-icon-trash"></i></a></td>
</script>
输出
示例 3: (使用addTemplate来拥有您自定义样式的添加模板,如下拉列表、输入框)
诸如点击一个不在 grid 内部但位于 grid DOM 外部的按钮来添加新条目等需求。要启用此类 addTemplate,您需要使用两个字段:addEnabled 和addTemplate
Grid 绑定
this.gridWithAddTemplate = new ko.simpleGrid.viewModel({
data: this.studentModel.students,
columns: [{ headerText: "Roll No", rowText: "" }, { headerText: "Name", rowText: "" }, { headerText: "View Marks", rowText: "" }, { headerText: "Actions", rowText: "" }],
pageSize: 10,
columnTemplate: "gridAddStudentStudent",
addEnabled: studentModel.addEnabled,
addTemplate: "addStudentTemplate",
ViewModel: studentModel
});
ViewModel
self.addEnable=ko.observable(false);
self.EnableAdd = function () {
self.addEnabled(true);
};
self.cancelEdit = function () {
self.addEnabled(false);
};
self.AddStudent = function () {
self.student.marks = { maths: 90, physics: 82, chemistry: 80 };
self.student.srNo = self.srCounter();
self.students.push(self.student);
self.student = new student();
self.addEnabled(false);
self.srCounter(self.srCounter() + 1);
};
模板: (2个模板,一个用于添加行,一个用于整个 grid(与上面相同))
<script id="gridAddStudentStudent" type="text/html">
<td data-bind="text: srNo"></td>
<td data-bind="text: name"></td>
<td style="width:166px;"><a href="#" data-bind="click: $parent.ViewModel.ViewMarks">View marks</a></td>
<td style="width:150px;"></td>
</script>
<script id="addStudentTemplate" type="text/html">
<!-- ko with: ViewModel.student -->
<td><input type="text" class="form-control input-sm" data-bind="value: $parent.ViewModel.srCounter" disabled="disabled"/></td>
<td><input type="text" class="form-control input-sm" data-bind="value: name"/></td>
<td>View marks</td>
<td style="width:150px;text-align: center;">
<a href="#" data-bind="click: $parent.ViewModel.AddStudent" style="margin-right:10px;" title="Save"><i class="glyphicon windows-icon-save"></i></a> <span style="border-left:2px solid #F4F4F4;"></span> <a href="#" data-bind="click: $parent.ViewModel.cancelEdit" style="margin-left:10px;" title="Cancel"><i class="glyphicon windows-icon-cancel"></i></a>
</td>
<!-- /ko -->
</script>
输出
当您点击“添加学生”时,它会在 grid 顶部添加一个新条目,如下所示。
当您输入文本并点击保存时,它将像这样添加到 grid 中。
示例 4: (使用hasMultiSelect功能并将其绑定到您的 ViewModel 属性,以及在选择行之前和之后处理预处理和后处理操作)
Grid 绑定
对于您的多选模板,您需要在 grid 中指定两个字段:hasMultiSelect 和headerMultiselectTemplate ,并在您的 grid 模板中添加第一行作为复选框,以便将每一列绑定到您的 checked 属性。
this.gridWithSelectAll = new ko.simpleGrid.viewModel({
data: this.studentModel.students,
columns: [{ headerText: "Roll No", rowText: "" }, { headerText: "Name", rowText: "" }, { headerText: "View Marks", rowText: "" }],
pageSize: 10,
columnTemplate: "gridWithSelectAll",
hasMultiSelect: true,
headerMultiselectTemplate: "mainGridMultiSelectTemplate",
ViewModel: studentModel
});
ViewModel
self.selectedStudents = ko.observableArray();
self.selectedAllStudents = ko.pureComputed({
read: function () {
return self.selectedStudents().length === self.students().length;
},
write: function (value) {
self.selectedStudents(value ? self.students().slice(0) : []);
}
});
模板
要使用多选模板,请指定 header select all 模板,以便您可以将其绑定到您的进一步处理属性。在主 grid 模板中,添加一行 <td><input type="checkbox"/></td> 作为第一行,并将其绑定到您的 ViewModel 属性以进行进一步处理。
<script id="gridWithSelectAll" type="text/html">
<script id="gridWithSelectAll" type="text/html">
<th style="text-align: center; width: 50px;"><input type="checkbox" data-bind="attr:{id:srNo+'_'+name},checkedValue: $data, checked: $parent.ViewModel.selectedStudents" /><label data-bind="attr:{for:srNo+'_'+name}"></label></th>
<td data-bind="text: srNo"></td>
<td data-bind="text: name"></td>
<td><a href="#" data-bind="click: $parent.ViewModel.ViewMarks">View marks</a></td>
</script>
<script id="mainGridMultiSelectTemplate" type="text/html">
<th style="text-align: center; width: 50px;"><input type="checkbox" id="srSelectAll" data-bind="checked: ViewModel.selectedAllStudents" /><label for="srSelectAll"></label></th>
</script>
输出
当您选择行时,正如我所绑定显示的已选学生姓名,它将如下所示。
当您点击“全选”时,它将如下所示。
您可以通过添加更多记录并使用分页器前后切换来查看分页功能。该站点使用了 bootstrap 进行样式设计。在代码中,您会找到 knockoutgrid.css,它包含了 grid 的样式,site.css 包含了站点的布局样式,自定义复选框样式以在不同浏览器中获得一致的复选框外观。
分页示例屏幕
提前感谢您的阅读 :-P