【问题标题】:Checkbox onclick in knockout is not updating viewmodel剔除中的复选框 onclick 未更新视图模型
【发布时间】:2017-11-17 17:00:35
【问题描述】:

我有复选框列表,单击任何复选框我需要获取所有选中的复选框。为此,我调用了 java 脚本函数“ChangeColumnSelection”。

问题是,单击的复选框不会立即更新视图模型。当我单击下一个文本框时,我看到之前的复选框值在视图模型中得到了更新。

 <ul class="list-group" data-bind="foreach: SelectionColumnList">
      <li class="list-group-item">
          <input type="checkbox" data-bind="attr: {onclick: 'javascript:ChangeColumnSelection(\'' + ColumnID + '\')'}, checked: IsSelected"
                        class="pull-xs-left push-down rightmargin" />
          <span data-bind="text: ColumnName"></span>
     </li>
 </ul>

更新:

我的视图模型是

  var dynamicGridViewModel = {
        SelectionColumnList: ko.observableArray([])
   }; 

    selectionInfo.ColumnID = columnInfo.ColumnID;
    selectionInfo.ColumnName = columnInfo.ColumnName;
    selectionInfo.DisplayOrder = columnInfo.DisplayOrder;
    selectionInfo.SortType = 'None';
    selectionInfo.IsSelected = true;
    dynamicGridViewModel.SelectionColumnList.push(selectionInfo);

【问题讨论】:

    标签: javascript java knockout.js


    【解决方案1】:

    您不需要onclick 事件。您只需使用 checked binding 即可实现此目的:

    var array = [{
      ColumnID: 1,
      ColumnName: "ColumnName 1"
    }, {
      ColumnID: 2,
      ColumnName: "ColumnName 2"
    }]
    
    var viewModel = function() {
      var self = this;
      self.SelectionColumnList = ko.observableArray(array);
      
      // no need to populate the array manually. Knockout will take care of it
      self.chosenItems = ko.observableArray();
    
      // every time chosenItems array changes, subscribe callback function gets triggered
      self.chosenItems.subscribe(function() {
        console.log(self.chosenItems());
      })
    }
    
    ko.applyBindings(new viewModel());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    <ul class="list-group" data-bind="foreach: SelectionColumnList">
      <li class="list-group-item">
        <input type="checkbox" data-bind="checkedValue: ColumnID, checked: $parent.chosenItems" />
        <span data-bind="text: ColumnName"></span>
      </li>
    </ul>

    这里,ColumnId 设置为checkbox 输入的值。因此,chosenItems 数组将是选定ColumnIds 的数组。

    Knockout 的伟大之处在于,它不仅允许 primitive typescheckedValue 的字符串、数字或布尔值,还允许对象。如果您希望将整个Column 对象填充到chosenItems 中,那么您可以像这样设置checkedValue

    <input type="checkbox" data-bind="checkedValue: $data, checked: $parent.chosenItems" />
    

    如果您想在更改任何复选框的状态时执行某些操作,您可以在subscribe 回调中执行该操作。每次数组更改时都会触发此函数。

    (另外,添加click binding 的正确方法是data-bind="click: clickFunction"

    更新:

    您使用对象字面量作为视图模型。我建议您创建 viewModel 函数并使用 new 运算符。如果要将checked 绑定到Column 的布尔属性,则可以创建computed 属性和subscribe 到该计算属性:

    var columns = [{
      ColumnID: 1,
      ColumnName: "ColumnName 1",
      IsSelected: false
    }, {
      ColumnID: 2,
      ColumnName: "ColumnName 2",
      IsSelected: true
    }];
    
    var viewModel = function() {
      var self = this;
      self.SelectionColumnList = ko.observableArray([]);
    
      // this property has the selected ColumnIds
      self.selectedItems = ko.computed(() => {
        // If you're using ES6 systax
        // return self.SelectionColumnList()
        //  .filter(column => column.IsSelected())
        //   .map(column => column.ColumnID);
    
        // out of the columns, get the ColumnIds with IsSelected as true
        return self.SelectionColumnList()
          .filter(function(column) {
            return column.IsSelected();
          })
          .map(function(column) {
            return column.ColumnID
          });
      });
    
      // gets triggered everytime checkbox is checked/unchecked
      self.selectedItems.subscribe(function() {
        console.log(self.selectedItems());
      });
    }
    
    // create a new instance of the viewmodel
    var dynamicGridViewModel = new viewModel();
    
    // loop through the columns and populate the observableArray
    columns.forEach(function(columnInfo) {
      var selectionInfo = {};
    
      selectionInfo.ColumnID = columnInfo.ColumnID;
      selectionInfo.ColumnName = columnInfo.ColumnName;
    
      // this property must be an observable
      selectionInfo.IsSelected = ko.observable(columnInfo.IsSelected);
    
      dynamicGridViewModel.SelectionColumnList.push(selectionInfo);
    })
    
    ko.applyBindings(dynamicGridViewModel);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    <ul class="list-group" data-bind="foreach: SelectionColumnList">
      <li class="list-group-item">
        <input type="checkbox" data-bind="checked: IsSelected" />
        <span data-bind="text: ColumnName"></span>
      </li>
    </ul>

    Here's a fiddle for testing

    【讨论】:

    • 感谢您的回答。我按照您的建议添加了单击绑定,但是单击事件不仅会在单击时触发,还会在将数据填充到视图模型时触发。
    • @sivaprakash 我添加了click 绑定文档作为附加资源。在你的情况下你不需要它。您是否完全忽略了我在点击绑定部分上面写的内容:D 您需要更改您的checked 绑定。阅读有关如何正确实施检查绑定的答案。浏览我添加的文档链接。点击Run code snippet查看工作示例
    • 谢谢,点击问题已解决。我希望 checkValue 与布尔属性绑定,并且 Checked 应该将整个对象推送到 selectedItems 视图模型
    • @sivaprakash 我假设每个Column 都有一个IsSelected 属性?请将您的视图模型的所有相关部分添加到问题中。
    • dynamicGridViewModel 是一个函数。你不能像dynamicGridViewModel.FilterColumnList 一样访问FilterColumnList。您需要使用new 运算符创建一个对象。这类似于 class 在 C# 或 java 中的工作方式。您无法通过classname.property 访问该物业。您需要首先创建该类的实例。 So in javascript, it is done by using the new keyword against a function。像这样:var gridInstance = new dynamicGridViewModel()。然后使用gridInstance.FilterColumnList
    猜你喜欢
    • 2014-12-04
    • 1970-01-01
    • 2023-03-07
    • 2011-09-08
    • 2014-03-12
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 2014-07-08
    相关资源
    最近更新 更多