使用 ko.computed 创建的 table 无法使用 Knockout 点击处理程序
Knockout click handler not working for table created using ko.computed
我正在尝试将 table 绑定到下拉菜单。这是我的要求:
下拉列表包含菜单列表。
一个菜单可以有许多关联的模块,这些模块显示在所选菜单项的 table 中。
模块不必与菜单项相关联,在这种情况下,它被视为在所选菜单项之间共享。
这是我的屏幕示例:
在示例中,您可以看到 CommonShellModule 是共享的,这意味着 CommonShellModule 将为所有菜单列出。
这是我目前拥有的:
ViewModel:
var ModuleIndexViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
self.selectedMenu = ko.observable();
self.selectedMenuModules = ko.computed(function () {
if (self.selectedMenu()) {
//display modules for the selected menu or where they are not associated to a menu
var modules = ko.utils.arrayFilter(self.Modules(), function (module) {
return self.isModuleAssociatedToCurrentMenuSelection(module) || self.isSharedModule(module);
});
//return a sorted list of modules
return modules.sort(function (left, right) {
return left.Name() > right.Name() ? 1 : -1;
});
}
return null;
});
self.isModuleAssociatedToCurrentMenuSelection = function (module) {
if (self.selectedMenu()) {
return module.MenuId() == self.selectedMenu().Id()
}
return false;
}
self.isSharedModule = function (module) {
return module.MenuId() == null;
}
self.handleSharedCheckboxClick = function (module) {
if (self.isSharedModule(module)) {
module.MenuId(null);
}
else {
module.MenuId(self.selectedMenu().Id());
}
return true; //allow the default click event action
}
}
型号:
被映射的模型(这些模型被序列化并传递到这个视图模型):
public class IndexViewModel
{
public IEnumerable<MenuViewModel> Menus { get; set; }
public IEnumerable<ModuleViewModel> Modules { get; set; }
}
public class MenuViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ModuleViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int? MenuId { get; set; }
}
查看:
...
<div class="form-group top-buffer">
<label class="control-label" for="menu">Menu</label>
<select id="menu" class="form-control" data-bind="options: Menus, optionsText: 'Name', value: selectedMenu"></select>
</div>
<div class="row top-buffer">
<div class="col-lg-12">
<table class="table table-striped">
<thead>
<tr>
<th class="col-lg-6">Module Name</th>
<th class="col-lg-3">Shared</th>
<th class="col-lg-3"></th>
</tr>
</thead>
<tbody data-bind="foreach: selectedMenuModules">
<tr>
<td data-bind="text: Name"></td>
<td><input type="checkbox" data-bind="checked: $parent.isSharedModule($data), click: $parent.handleSharedCheckboxClick" /></td>
<td><a href="#">Edit</a> | <a href="#">Details</a> | <a href="#">Delete</a></td>
</tr>
</tbody>
</table>
</div>
</div>
...
问题是 javascript handleSharedCheckboxClick
不工作,我不知道为什么。每次单击共享复选框时都会执行它,但是当我更新此函数中的模块值时,不会重新计算计算出的剔除值,因此 table 保留以前的值。
如果有任何建议可以解决这个问题,我将不胜感激。
编辑:我的错,用 findle 玩了一下,正在观察该模块值,看起来问题出在这里:
self.handleSharedCheckboxClick = function (module) {
if (self.isSharedModule(module)) {
module.MenuId(null);
}
如果共享模块,则该值已经为空,因此不会更改该值,修改该代码添加 ! 之类的这个:
self.handleSharedCheckboxClick = function (module) {
if (!self.isSharedModule(module)) {
module.MenuId(null);
}
让它按你想要的方式工作,在菜单项值更新之间保存共享状态(单击选中的复选框,该行不再共享但绑定到当前菜单项,再次单击它并返回共享)
jsfindle: http://jsfiddle.net/yj1s9qod/
我正在尝试将 table 绑定到下拉菜单。这是我的要求:
下拉列表包含菜单列表。
一个菜单可以有许多关联的模块,这些模块显示在所选菜单项的 table 中。
模块不必与菜单项相关联,在这种情况下,它被视为在所选菜单项之间共享。
这是我的屏幕示例:
在示例中,您可以看到 CommonShellModule 是共享的,这意味着 CommonShellModule 将为所有菜单列出。
这是我目前拥有的:
ViewModel:
var ModuleIndexViewModel = function (data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
self.selectedMenu = ko.observable();
self.selectedMenuModules = ko.computed(function () {
if (self.selectedMenu()) {
//display modules for the selected menu or where they are not associated to a menu
var modules = ko.utils.arrayFilter(self.Modules(), function (module) {
return self.isModuleAssociatedToCurrentMenuSelection(module) || self.isSharedModule(module);
});
//return a sorted list of modules
return modules.sort(function (left, right) {
return left.Name() > right.Name() ? 1 : -1;
});
}
return null;
});
self.isModuleAssociatedToCurrentMenuSelection = function (module) {
if (self.selectedMenu()) {
return module.MenuId() == self.selectedMenu().Id()
}
return false;
}
self.isSharedModule = function (module) {
return module.MenuId() == null;
}
self.handleSharedCheckboxClick = function (module) {
if (self.isSharedModule(module)) {
module.MenuId(null);
}
else {
module.MenuId(self.selectedMenu().Id());
}
return true; //allow the default click event action
}
}
型号:
被映射的模型(这些模型被序列化并传递到这个视图模型):
public class IndexViewModel
{
public IEnumerable<MenuViewModel> Menus { get; set; }
public IEnumerable<ModuleViewModel> Modules { get; set; }
}
public class MenuViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ModuleViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int? MenuId { get; set; }
}
查看:
...
<div class="form-group top-buffer">
<label class="control-label" for="menu">Menu</label>
<select id="menu" class="form-control" data-bind="options: Menus, optionsText: 'Name', value: selectedMenu"></select>
</div>
<div class="row top-buffer">
<div class="col-lg-12">
<table class="table table-striped">
<thead>
<tr>
<th class="col-lg-6">Module Name</th>
<th class="col-lg-3">Shared</th>
<th class="col-lg-3"></th>
</tr>
</thead>
<tbody data-bind="foreach: selectedMenuModules">
<tr>
<td data-bind="text: Name"></td>
<td><input type="checkbox" data-bind="checked: $parent.isSharedModule($data), click: $parent.handleSharedCheckboxClick" /></td>
<td><a href="#">Edit</a> | <a href="#">Details</a> | <a href="#">Delete</a></td>
</tr>
</tbody>
</table>
</div>
</div>
...
问题是 javascript handleSharedCheckboxClick
不工作,我不知道为什么。每次单击共享复选框时都会执行它,但是当我更新此函数中的模块值时,不会重新计算计算出的剔除值,因此 table 保留以前的值。
如果有任何建议可以解决这个问题,我将不胜感激。
编辑:我的错,用 findle 玩了一下,正在观察该模块值,看起来问题出在这里:
self.handleSharedCheckboxClick = function (module) {
if (self.isSharedModule(module)) {
module.MenuId(null);
}
如果共享模块,则该值已经为空,因此不会更改该值,修改该代码添加 ! 之类的这个:
self.handleSharedCheckboxClick = function (module) {
if (!self.isSharedModule(module)) {
module.MenuId(null);
}
让它按你想要的方式工作,在菜单项值更新之间保存共享状态(单击选中的复选框,该行不再共享但绑定到当前菜单项,再次单击它并返回共享)
jsfindle: http://jsfiddle.net/yj1s9qod/