【问题标题】:UI does not update when Updating ObservableArray更新 ObservableArray 时 UI 不更新
【发布时间】:2013-07-25 15:51:43
【问题描述】:

当用户单击 UI 中列表(html 表 tblAllCert)中的一行时,我会触发一个单击事件以填充另一个应填充第二个 html 表(tblCertDetails)的可观察数组。我的点击事件触发,我可以看到数据返回,我可以看到可观察数组中的数据,但我的视图没有更新。

这里是代码中序列的概述-

 1. user clicks on row from html table tblAllCert, which fires selectThing method.
 2. In viewmodel code, selectThing passes the row data from the row selected to the GetCertificateDetails(row) method.
 3. GetCertificateDetails(row) method calls getCertDetails(CertificateDetails, source) function on my data service (the data service gets data from a web api).  getCertDetails(CertificateDetails, source) function returns an observable array.
 4. once the data is returned to selectThing, CertificateDetails observable array is populated.  It does get data to this point. 

第 5 步应该更新 UI(特别是 tblCertDetails html 表),但是 UI 没有更新。

这是我的看法-

                                    <table id="tblAllCert" border="0" class="table table-hover" width="100%">
                                    <tbody data-bind="foreach: allCertificates">
                                        <tr id="AllCertRow" style="cursor: pointer" data-bind="click: $parent.selectThing, css: { highlight: $parent.isSelected() == $data.lwCertID }">
                                            <td>
                                                <ul style="width: 100%">

                                                    <b><span data-bind="    text: clientName"></span>&nbsp;(<span data-bind="    text: clientNumber"></span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span data-bind="    text: borrowBaseCount"></span>&nbsp;Loan(s)&nbsp;</b>
                                                    <br />
                                                    Collateral Analyst:&nbsp;<span data-bind="    text: userName"></span>
                                                    <br />
                                                    Certificate:&nbsp;<span data-bind="text: lwCertID"></span>&nbsp;&nbsp;Request&nbsp;Date:&nbsp;<span data-bind="    text: moment(requestDate).format('DD/MMM/YYYY')"></span>
                                            </td>
                                        </tr>
                                    </tbody>
                                </table>


                                <table id="tblCertDetails" border="0" class="table table-hover" width="100%">
                                <tbody data-bind="foreach: CertificateDetails">
                                    <tr id="Tr1" style="cursor: pointer">
                                        <td>
                                            <ul style="width: 100%">
                                                <b>Loan:&nbsp;<span data-bind="    text: loanNum"></span>
                                        </td>
                                    </tr>
                                </tbody>

                            </table>

我的视图模型-

 define(['services/logger', 'durandal/system', 'durandal/plugins/router', 'services/CertificateDataService'],
function (logger, system, router, CertificateDataService) {
    var allCertificates = ko.observableArray([]);
    var myCertificates = ko.observableArray([]);
    var isSelected = ko.observable();
    var serverSelectedOptionID = ko.observable();

    var CertificateDetails = ko.observableArray([]);

    var serverOptions = [
    { id: 1, name: 'Certificate', OptionText: 'lwCertID' },
    { id: 2, name: 'Client Name', OptionText: 'clientName' },
    { id: 3, name: 'Client Number', OptionText: 'clientNumber' },
    { id: 4, name: 'Request Date', OptionText: 'requestDate' },
    { id: 5, name: 'Collateral Analyst', OptionText: 'userName' }
    ];

    var activate = function () {
        // go get local data, if we have it
        return SelectAllCerts(), SelectMyCerts();
    };


    var vm = {
        activate: activate,
        allCertificates: allCertificates,
        myCertificates: myCertificates,
        CertificateDetails: CertificateDetails,
        title: 'Certificate Approvals',
        SelectMyCerts: SelectMyCerts,
        SelectAllCerts: SelectAllCerts,
        theOptionId: ko.observable(1),
        serverOptions: serverOptions,
        serverSelectedOptionID: serverSelectedOptionID,
        SortUpDownAllCerts: SortUpDownAllCerts,
        isSelected: isSelected,
        selectThing: function (row, event) {
            CertificateDetails = GetCertificateDetails(row);
            isSelected(row.lwCertID);
        }

    };



    serverSelectedOptionID.subscribe(function () {
        var sortCriteriaID = serverSelectedOptionID();
        allCertificates.sort(function (a, b) {
            var fieldname = serverOptions[sortCriteriaID - 1].OptionText;

            if (a[fieldname] == b[fieldname]) {
                return a[fieldname] > b[fieldname] ? 1 : a[fieldname] < b[fieldname] ? -1 : 0;
            }

            return a[fieldname] > b[fieldname] ? 1 : -1;

        });

    });

    return vm;



    function GetCertificateDetails(row) {
        var source = {
            'lwCertID': row.lwCertID,
            'certType': row.certType,
        }
        return CertificateDataService.getCertDetails(CertificateDetails, source);
    }

    function SortUpDownAllCerts() {
        allCertificates.sort();
    }


    function SelectAllCerts() {
        return CertificateDataService.getallCertificates(allCertificates);
    }

    function SelectMyCerts() {
        return CertificateDataService.getMyCertificates(myCertificates);
    }

});

以及来自我的数据服务的相关摘录-

        var getCertDetails = function (certificateDetailsObservable, source) {
        var dataObservableArray = ko.observableArray([]);
        $.ajax({
            type: "POST",
            dataType: "json",
            url: "/api/caapproval/CertDtlsByID/",
            data: source,
            async: false,
            success: function (dataIn) {

                ko.mapping.fromJSON(dataIn, {}, dataObservableArray);

            },
            error: function (error) {
                jsonValue = jQuery.parseJSON(error.responseText);
                //jError('An error has occurred while saving the new part source: ' + jsonValue, { TimeShown: 3000 });
            }

        });
        return dataObservableArray;
    }

关于为什么 UI 不更新的想法?

【问题讨论】:

    标签: javascript knockout.js requirejs single-page-application knockout-mvc


    【解决方案1】:

    当您使用 Knockout 数组时,您应该更改数组的内容,而不是对数组本身的引用。在selectThing,当你设置

    CertificateDetails = GetCertificateDetails(row);
    

    分配给CertificateDetails 的新observableArray 与KO 绑定到您的表的observableArray 不同。

    不过,您已经非常接近解决方案了。在您的 AJAX 成功回调中,您可以直接映射到参数 certificateDetailsObservable,而不是创建一个新的 dataObservableArray 并映射到它。 ko.mapping.fromJSON 应该替换表绑定数组的内容(你也可以去掉selectThing 中的赋值)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多