Select 选中多个列表中的复选框时的所有复选框

Select All checkboxes on check of checkbox in multiple lists

有一种情况,timelsot 列表列在天数下,并且此数据是动态来自服务器的。现在用户应该 select 给定 day.Something 的所有时隙,就像在这个 fiddle. I am trying to follow the example on knockout documentation 中一样,但是在这个例子中 header 复选框不是动态的。同样,我如何维护多个列表的引用?

<ul class="header" data-bind="foreach: days">
<li>
    <label>
        <input type="checkbox" data-bind="attr: { id: 'chk' + id }"/>
        <span data-bind="text: name"></span>
    </label>
    <ul data-bind="foreach: timeslots">
        <li>
            <label>
                <input type="checkbox" data-bind="attr: { id: 'chk' + id }"/>
                <span data-bind="text: name"></span>
            </label>
        </li>    
    </ul>
</li>    

    function MyViewModel() {

    this.days = ko.observableArray([
        { name:"Sunday", id:1 , timeslots : [{ name:"10:00 - 11:00", id:10},{ name:"10:00 - 11:00", id:11},{ name:"10:00 - 11:00", id:12}] },
        { name:"Monday", id:2 , timeslots : [{ name:"10:00 - 11:00", id:20},{ name:"10:00 - 11:00", id:21},{ name:"10:00 - 11:00", id:22}] },
        { name:"Tuesday", id:3 , timeslots : [{ name:"10:00 - 11:00", id:30},{ name:"10:00 - 11:00", id:31},{ name:"10:00 - 11:00", id:32}] },
        { name:"Wednesday", id:4 , timeslots : [{ name:"10:00 - 11:00", id:40},{ name:"10:00 - 11:00", id:41},{ name:"10:00 - 11:00", id:42}] },
        { name:"Thursday", id:5 , timeslots : [{ name:"10:00 - 11:00", id:50},{ name:"10:00 - 11:00", id:51},{ name:"10:00 - 11:00", id:52}] },
        { name:"Friday", id:6 , timeslots : [{ name:"10:00 - 11:00", id:60},{ name:"10:00 - 11:00", id:61},{ name:"10:00 - 11:00", id:62}] },
        { name:"Saturday", id:7 , timeslots : [{ name:"10:00 - 11:00", id:70},{ name:"10:00 - 11:00", id:71},{ name:"10:00 - 11:00", id:72}] }
    ]);
    this.selectedDays = ko.observableArray([ 
        { id:1 , timeslots : [{ name:"10:00 - 11:00", id:10},{ name:"10:00 - 11:00", id:12}] },
        { id:2 , timeslots : [{ name:"10:00 - 11:00", id:21}] }
    ]);
}
ko.applyBindings(new MyViewModel());

我想要实现的功能是示例 2:Selecting/deselecting 淘汰文档中的所有项目 link 但我不知道如何实现我场景中的 pureComputed 函数。

最好先将普通对象映射到某种可以具有可观察或计算属性的视图模型。

然后,

  1. 你给每个 timeslot 一个 observable 布尔值 checked 属性,
  2. 你给每个day一个可写计算checked属性

checked 属性 天的write 函数设置了所有内部timeslots。它的 read 函数 returns 是否至少检查 一个 个时隙。

最后,您创建一个 pureComputed 状态,将视图模型解析回普通的 javascript 数据结构。为此,我首先过滤掉未选中的日期。然后,对于有检查时间段的每一天,我收集检查项目的标签。


这是一个示例,仅抽象为 GroupItem 模型。您应该能够将其转换为您自己的格式。如果您需要更多帮助,请告诉我。

function Item(label) {
  this.label = label;
  this.checked = ko.observable(false);
}

Item.forLabel = str => new Item(str);

function Group(label, items) {
  this.label = label;
  this.items = items.map(Item.forLabel);
  
  this.checked = ko.computed({
    read: () => this.items.some(i => i.checked()),
    write: val => { this.items.forEach(i => i.checked(val)); }
  });
}

Group.prototype.toJS = function() {
  // Define the format of your selected state here:
  return { 
    label: this.label,
    items: this.items
      .filter(i => i.checked())
      .map(i => i.label)
  };
}


const groups = [
  new Group("colors", [ "red", "green", "blue" ]),
  new Group("directions", [ "up", "down" ])
];

const selection = ko.pureComputed(
  () => groups
    .filter(g => g.checked())
    .map(g => g.toJS())
)

ko.applyBindings({ groups, selection });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: groups">
  <li>
    <label>
      <input type="checkbox" data-bind="checked: checked">
      <span data-bind="text: label"></span>
    </label>
    <ul data-bind="foreach: items">
      <li>
        <label>
          <input type="checkbox" data-bind="checked: checked">
          <span data-bind="text: label"></span>
        </label>
      </li>
    </ul>
  </li>
</ul>


<pre data-bind="text: JSON.stringify(selection(), null, 4)" style="background: #efefef; padding: 1rem;"></pre>