knockout.js 敲除选中表列中所有复选框

ctehm74n  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(143)

我是第一次使用knockout,并尝试实现一个第一列为复选框的表格。当我点击表头时,整列都应该被选中/取消选中。目前,当我点击表格行(所有行都被选中/取消选中)时,它可以工作,但在表头上不行。请让我知道我的代码有什么问题!以下是我的部分代码:

<table>
            <tr>
                <th><input type="checkbox" data-bind="click: selectAll"></th>
                <th>Notes</th>
            </tr>

            <tbody data-bind="foreach: DocumentRows">
                <tr>
                    <td><input type="checkbox" data-bind="checked: $parent.IsSelected"></td>
             <td><data-bind="text: Notes"></td>
</tr>
            </tbody>
        </table>

       // Script.ts

        ```
        define(['knockout', 'jquery', 'text!./Template'], (ko, $, htmlString) => {
        //Document
        class Document {
                Id: KnockoutObservable<number>;      
                Notes: KnockoutObservable<string>;        
                constructor(data?) {
                    this.Id = ko.observable(0);          
                    this.Notes = ko.observable("").extend({ defaultValue: "" });            
                    if (data != null) {
                        ko.mapping.fromJS(data, {}, this);
                    }
                }        
            };

        //DocumentS VIEW MODEL
        class DocumentsViewModel {
        DocumentRows: KnockoutObservableArray<Document>;
        IsSelected: KnockoutObservable<boolean>;

        constructor(params) {
        this.DocumentRows = ko.observableArray([]);
        this.IsSelected = ko.observable(false);//
        this.InitComputed();       
               this.Load();
        }
        InitComputed = () => {
        selectAll = (Document: DocumentsViewModel) => {      
                    var doc = Document.DocumentRows;           
                    ko.utils.arrayForEach(doc(), function (item) {
                        item.IsSelected(true);
                    });
                }

        Load = () => {
                    DocumentsApiService.GetDocumentList(this);
                }

        }

        //API SERVICE
        class DocumentsApiService {
                static GetDocumentList = (model: DocumentsViewModel) => {
                    $.ajax({
                        url: buildUrl(model.LoadListURL, { 'id': model.ObjectId(), 'additionalId': model.AdditionalId() }),
                        type: 'POST',
                        data: ko.mapping.toJSON(model.Filter),
                        contentType: 'application/json; charset=utf-8'
                    }).done(allData => {
                        var mapped = ko.mapping.fromJS(allData, DocumentsMapping);
                        model.DocumentRows(mapped.DocumentRows());
                        model.Filter.TotalCount(mapped.TotalCount());
                        model.Filter.PageIndex(mapped.Filter.PageIndex());
                        CalcCountTableStatus(model.Filter.PageIndex(), model.Filter.PageSize(), model.Filter.TotalCount(), 'documents-count-status-line');
                    }).fail(data => {
                        TSCore.OnFailure(data);
                    });
                }
        }

            return { viewModel: DocumentsViewModel, template: htmlString }
        });
        ```
ki1q1bka

ki1q1bka1#

当实现这样的选择特征时,通常有两种方法。

Document级别具有可观察的isSelected布尔值

isSelected可观测性放在Document模型上,而no放在DocumentsViewModel模型上,因为每个文档都必须包含信息,无论它是否被选中。
我猜您试图实现这种方法,但是乍一看,您没有将IsSelected放在正确的位置。另外,如果您将IsSelected移动到文档中,那么在您看来,不要使用$parent.IsSelected,而只使用IsSelected

DocumentsViewModel级别维护一个selectedDocuments可观察文档数组

通过这种方式,您可以拥有一个包含所有当前选定文档的可观察数组,并在选择所有这些文档时保持该数组(如将所有行推送到选定内容)
在视图中,必须使用父引用来确定是否选择了文档,例如$parent.selectedDocuments.indexOf($data) >= 0 .
现在我不会讨论这两种方法的所有优点和缺点,但是如果可以用IsSelected可观察对象扩展文档模型,我建议使用第一种方法。

其他备注

现在还不清楚您想用InitComputeds实现什么。

public selectAll(): void {      
    ko.utils.arrayForEach(this.DocumentRows(), function (item) {
        item.IsSelected(true);
    });
}

如果您使用此语法,则必须在视图级别绑定函数,如$data.selectAll.bind($data)。如果您不希望这样,而只希望使用纯selectAll,则可以使用箭头函数作为字段语法,如以下所示。

public selectAll = ():void => {
    ko.utils.arrayForEach(this.DocumentRows(), function (item) {
        item.IsSelected(true);
    });
}

希望我能给予你一些有价值的提示。

5sxhfpxr

5sxhfpxr2#

因此,更改表格标题后:

<th><input type="checkbox" data-bind="click: selectAll, checked: selectedAll"></th>

表体:

<td><input type="checkbox" data-bind="checked: IsSelected"></td>

脚本:

//Document
class Document {
    Id: KnockoutObservable<number>;        
    IsSelected: KnockoutObservable<boolean>;
    constructor(data?) {
        this.Id = ko.observable(0);
        this.Notes = ko.observable("").extend({ defaultValue: "" });          
        this.IsSelected = ko.observable(false);
        if (data != null) {
            ko.mapping.fromJS(data, {}, this);
        }
    }
};

//文档视图模型

class DocumentsViewModel {
    selectedAll: KnockoutObservable<boolean>;
  constructor(params) {
 this.selectedAll = ko.observable(false);
}
 InitComputed = () => {
this.selectedAll = ko.pureComputed({
                read: function () {
                    return this.selectedIds().length === this.DocumentRows().length;
                },
                write: function (value) {
                    this.selectedIds(value ? this.DocumentRows.slice(0) : []);
                },
                owner: this
            }
     selectAll = (): void => {
                if (this.selectedIds().length > 0) {
                    this.selectedIds.removeAll();
                    ko.utils.arrayForEach(this.DocumentRows(), function (item) {
                        item.IsSelected(false);
                    });
                } else {
                    ko.utils.arrayPushAll(this.selectedIds(), this.DocumentRows())
                    ko.utils.arrayForEach(this.DocumentRows(), function (item) {
                        item.IsSelected(true);
                    });
                }
            }
    }

当所有行都被选中时,它不显示要被选中的标题,当所有行都被选中时,它不显示要被选中的标题。

相关问题