第一次点击时没有反映可观察数组的变化 - KnockoutJS

时间:2016-06-04 11:02:54

标签: javascript jquery arrays knockout.js

我有一个可观察的数组用于复选框列表,我正在使用一个可观察的数组处理已检查的事件。

现在,当我进行更改时,数组的值会立即更新,但不会在DOM上反映出来。但当我点击其他一些项目时,更改就会反映出来。

简而言之,数组值的更改不会在第一次单击时反映出来,但在第二次单击时会反映出来。

这是我的代码:

        /*--- Factory Objects ---*/
    var ModelFactory = function () {
        this.ModelTitle = ko.observable();
        this.ModelId = ko.observable();
        this.FamilyId = ko.observable();
    }
    var SeriesFactory = function (SeriesTitle, SeriesId) {
        this.SeriesTitle = ko.observable();
        this.SeriesId = ko.observable();
    };
    var OptionsFactory = function (SelectionFlag, OptionTitle, OptionId, OptionPrice, OptionType, ModelId) {
        var self = this;
        this.OptionTitle = ko.observable();
        this.OptionId = ko.observable();
        this.OptionType = ko.observable();
        this.OptionPrice = ko.observable();
        this.ModelId = ko.observable();
        this.SelectionFlag = ko.computed(function () {
            return self.OptionType() === "0" ? self.OptionId() : null;
        });
        this.FormattedOptionPrice = ko.computed(function () {
            return "USD " + self.OptionPrice();
        });
    };
    /*--- Factory Objects End ---*/
    /*--- ViewModel ----*/
    function OpportunityViewModel() {
        var self = this;
        self.SeriesList = ko.observableArray([]);
        self.ModelList = ko.observableArray([]);
        self.OptionList = ko.observableArray([]);
        self.SelectedOptionsList = ko.observableArray([]);
        self.LoadSeries = function () {
            self.ClearFactory(self.SeriesList);
            for (var i = 0; i < familyList.length; i++) {
                self.SeriesList.push(new SeriesFactory().SeriesId(familyList[i].Id).SeriesTitle(familyList[i].FamilyTitle));
            }
        };
        self.LoadModels = function (seriesId) {
            self.ClearFactory(self.ModelList);
            for (var i = 0; i < productList.length; i++) {
                if (seriesId() === productList[i].FamilyId) {
                    self.ModelList.push(new ModelFactory().ModelId(productList[i].Id).ModelTitle(productList[i].ModelTitle).FamilyId(productList[i].FamilyId));
                }
            }
        };
        self.SeriesClick = function (seriesObject, event) {
            if (seriesObject !== null && typeof seriesObject !== 'undefined') {
                self.LoadModels(seriesObject.SeriesId);
            }
        };
        self.ModelClick = function (modelObject, event) {
            if (modelObject !== null && typeof modelObject !== 'undefined') {
                self.LoadOptions(modelObject.ModelId);
            }
        };
        self.LoadOptions = function (modelId) {
            self.ClearFactory(self.OptionList);
            for (var i = 0; i < optionList.length; i++) {
                if (modelId() === optionList[i].ModelId) {
                    self.OptionList.push(new OptionsFactory()
                        .OptionId(optionList[i].Id)
                        .OptionTitle(optionList[i].OptionTitle)
                        .OptionPrice(optionList[i].OptionPrice)
                        .OptionType(optionList[i].OptionType)
                        .ModelId(optionList[i].ModelId)
                        );
                    if (optionList[i].OptionType === "0") {
                        self.SelectedOptionsList.push(optionList[i].Id);
                    }
                }
            }
        };
        self.SelectedOptions = function (selectedItem) {
            console.clear();
            for (var i = 0; i < self.SelectedOptionsList().length; i++) {
                if (self.SelectedOptionsList()[i] === selectedItem.OptionId()) {
                    self.SelectedOptionsList.remove(selectedItem.OptionId());
                    console.log(JSON.stringify(self.SelectedOptionsList()));
                    return;
                }
            }
            self.SelectedOptionsList.push(selectedItem.OptionId());
            console.log(JSON.stringify(self.SelectedOptionsList()));
        };
        self.ClearFactory = function (observableFactory) {
            observableFactory([]);
        };
    }
    /*--- View Model End ---*/
    /*--- Init --- */
    $(function () {
        var opportunityVM = new OpportunityViewModel();
        opportunityVM.LoadSeries();
        ko.applyBindings(opportunityVM);
    });
    /*--- Init End ---*/

和模板

 <button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#productSearch">
    Launch Modal
</button>
<div class="modal fade" id="productSearch" role="dialog" aria-labelledby="productDialogTitle">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="productDialogTitle">Product Selection</h4>
            </div>
            <div class="modal-body">
                <div class="row">
                    <div class="col-md-4">
                        <div class="panel panel-primary">
                            <div class="panel-heading">
                                <h3 class="panel-title">Series Selection</h3>
                            </div>
                            <div class="panel-body">
                                <ul data-bind="foreach: SeriesList" id="ulFamilyList">
                                    <li><a class="btn btn-link series" data-bind="text: SeriesTitle, attr: {Id: SeriesId}, click: $parent.SeriesClick"></a></li>
                                </ul>
                            </div>
                            <div class="panel-footer">

                            </div>
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="panel panel-primary">
                            <div class="panel-heading">
                                <h3 class="panel-title">Model Selection</h3>
                            </div>
                            <div class="panel-body">
                                <ul id="ulModelList" data-bind="foreach: ModelList">
                                    <li><a class="btn btn-link productModel" data-bind="text: ModelTitle, attr:{Id: ModelId}, click: $parent.ModelClick"></a></li>
                                </ul>
                            </div>
                            <div class="panel-footer">

                            </div>
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="panel panel-primary">
                            <div class="panel-heading">
                                <h3 class="panel-title">Option Selection</h3>
                            </div>
                            <div class="panel-body">
                                <table class="table table-stripped table-hover table-bordered" id="ulOptionList" data-bind="foreach: OptionList">
                                    <tr class="optionListRow">
                                        <td>
                                            <input type="checkbox" data-bind="value: OptionId, click: $parent.SelectedOptions, checked: $parent.SelectedOptionsList" />
                                            <span data-bind="text: '&nbsp' + OptionTitle()"></span>
                                        </td>
                                        <td>
                                            <p data-bind="text: FormattedOptionPrice"></p>
                                        </td>
                                    </tr>
                                </table>
                            </div>
                            <div class="panel-footer">

                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div>
    </div>
</div>

我做错了什么?另外我只是另一个新手,刚刚开始使用KnockoutJS。如果专家们能够优化这些代码并展示他们的一些改进技能,我将不胜感激。

谢谢:)

更新

以下是我正在使用的一些测试数据。

        familyList = [
        { FamilyTitle: "3 Series", Id: "9e55c0ae-37d0-0d89-808f-acccfb58562f" },
        { FamilyTitle: "5 Series", Id: "3d9d6640-a8b5-b4ed-56d2-ef9d1d6f8544" },
        { FamilyTitle: "7 Series", Id: "c395c655-f302-852a-ccca-1a5e9bf10e0e" },
        { FamilyTitle: "X Series", Id: "3e31300f-1dcb-1d50-f796-c58c76cb4ab2" }
    ];
    productList = [
        { ModelTitle: "325i", Id: "e1d17dbf-3142-4bde-89bd-830caa09eb93", FamilyId: "9e55c0ae-37d0-0d89-808f-acccfb58562f" },
        { ModelTitle: "525i", Id: "9ac7da72-5224-6046-3913-c2700c486682", FamilyId: "3d9d6640-a8b5-b4ed-56d2-ef9d1d6f8544" },
        { ModelTitle: "X5", Id: "e64d76e4-73f8-36e5-9eca-27166bcc890b", FamilyId: "3e31300f-1dcb-1d50-f796-c58c76cb4ab2" },
        { ModelTitle: "X6", Id: "b104e806-5652-a21b-0180-a8956246a045", FamilyId: "3e31300f-1dcb-1d50-f796-c58c76cb4ab2" },
        { ModelTitle: "X3", Id: "b3447f56-a51b-a451-29de-26b4b3fd98e9", FamilyId: "3e31300f-1dcb-1d50-f796-c58c76cb4ab2" },
        { ModelTitle: "530i xDrive", Id: "30595eef-d0a7-a234-dc7f-6670a588c00e", FamilyId: "3d9d6640-a8b5-b4ed-56d2-ef9d1d6f8544" },
        { ModelTitle: "740Li", Id: "f19aed7c-f2a8-6777-4ed2-93ef2b717ac3", FamilyId: "c395c655-f302-852a-ccca-1a5e9bf10e0e" },
        { ModelTitle: "325Li xDrive", Id: "eaabc23e-d040-34ee-1e59-b1f6b9bc3cff", FamilyId: "9e55c0ae-37d0-0d89-808f-acccfb58562f" },
        { ModelTitle: "M3", Id: "e200ffba-e70c-e743-e8b5-8dd39061bd7d", FamilyId: "9e55c0ae-37d0-0d89-808f-acccfb58562f" },
        { ModelTitle: "M5", Id: "3d37e4b7-61be-a467-d4b9-aba784dea17b", FamilyId: "3d9d6640-a8b5-b4ed-56d2-ef9d1d6f8544" },
        { ModelTitle: "320i", Id: "398ee891-4847-5f29-b7c9-b98249d6b582", FamilyId: "9e55c0ae-37d0-0d89-808f-acccfb58562f" },
        { ModelTitle: "550i Sedan", Id: "49e7ca96-d801-ff2c-c112-245b1707e6c1", FamilyId: "3d9d6640-a8b5-b4ed-56d2-ef9d1d6f8544" },
        { ModelTitle: "750Li xDrive", Id: "9193cc24-58a8-cb8b-c7d4-f10eddb110b6", FamilyId: "c395c655-f302-852a-ccca-1a5e9bf10e0e" },
    ];
    optionList = [
        { Id: "option01", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "120", OptionType: "0", OptionTitle: "325i Moonroof" },
        { Id: "option02", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "150", OptionType: "1", OptionTitle: "325i 19\" Alloy Wheels" },
        { Id: "option03", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "180", OptionType: "1", OptionTitle: "325i Remote Keyless Entry" },
        { Id: "option04", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "200", OptionType: "0", OptionTitle: "325i Power Locks" },
        { Id: "option05", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "520", OptionType: "0", OptionTitle: "325i 6 Speed Automatic" },
        { Id: "option06", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "600", OptionType: "1", OptionTitle: "325i Pedal Shifters" },
        { Id: "option07", ModelId: "e1d17dbf-3142-4bde-89bd-830caa09eb93", OptionPrice: "540", OptionType: "1", OptionTitle: "325i Heated Front and Back Seats" },
        { Id: "option06", ModelId: "f19aed7c-f2a8-6777-4ed2-93ef2b717ac3", OptionPrice: "690", OptionType: "1", OptionTitle: "740Li Touring Package" },
        { Id: "option09", ModelId: "f19aed7c-f2a8-6777-4ed2-93ef2b717ac3", OptionPrice: "960", OptionType: "0", OptionTitle: "740Li Illuminating" },
        { Id: "option10", ModelId: "9ac7da72-5224-6046-3913-c2700c486682", OptionPrice: "600", OptionType: "0", OptionTitle: "525i 20\" Alloy Wheels" },
        { Id: "option11", ModelId: "9ac7da72-5224-6046-3913-c2700c486682", OptionPrice: "320", OptionType: "0", OptionTitle: "525i Tech Package" },
        { Id: "option12", ModelId: "9ac7da72-5224-6046-3913-c2700c486682", OptionPrice: "542", OptionType: "1", OptionTitle: "525i Premium Package" },
        { Id: "option13", ModelId: "9ac7da72-5224-6046-3913-c2700c486682", OptionPrice: "520", OptionType: "1", OptionTitle: "525i Sports Package" },
        { Id: "option14", ModelId: "9ac7da72-5224-6046-3913-c2700c486682", OptionPrice: "540", OptionType: "0", OptionTitle: "525i Heated Back Seats" },
        { Id: "option15", ModelId: "9ac7da72-5224-6046-3913-c2700c486682", OptionPrice: "770", OptionType: "1", OptionTitle: "525i Smart Cruise Control" },
        { Id: "option16", ModelId: "e64d76e4-73f8-36e5-9eca-27166bcc890b", OptionPrice: "670", OptionType: "1", OptionTitle: "X5 Moonroof" },
        { Id: "option17", ModelId: "e64d76e4-73f8-36e5-9eca-27166bcc890b", OptionPrice: "450", OptionType: "0", OptionTitle: "X5 Blind Spot Detection" },
        { Id: "option18", ModelId: "b3447f56-a51b-a451-29de-26b4b3fd98e9", OptionPrice: "340", OptionType: "0", OptionTitle: "X3 Heated Seats" },
        { Id: "option19", ModelId: "9193cc24-58a8-cb8b-c7d4-f10eddb110b6", OptionPrice: "550", OptionType: "0", OptionTitle: "750Li Smart Stop System" },
        { Id: "option20", ModelId: "9193cc24-58a8-cb8b-c7d4-f10eddb110b6", OptionPrice: "870", OptionType: "0", OptionTitle: "750Li Blind Spot Detection" },
        { Id: "option21", ModelId: "e200ffba-e70c-e743-e8b5-8dd39061bd7d", OptionPrice: "230", OptionType: "0", OptionTitle: "M3 6 Cylinder Direct Injecton Engine" },
        { Id: "option22", ModelId: "e200ffba-e70c-e743-e8b5-8dd39061bd7d", OptionPrice: "450", OptionType: "1", OptionTitle: "M3 8 Speed Automatic Transmission" },
        { Id: "option23", ModelId: "e200ffba-e70c-e743-e8b5-8dd39061bd7d", OptionPrice: "650", OptionType: "0", OptionTitle: "M3 6 Speed Manual Transmission" },
        { Id: "option24", ModelId: "3d37e4b7-61be-a467-d4b9-aba784dea17b", OptionPrice: "980", OptionType: "1", OptionTitle: "M5 Automatic Moonroof" },
    ];

**更新2 **

这里我把所有东西放在JSFiddle

https://jsfiddle.net/hhkrjus3/

2 个答案:

答案 0 :(得分:0)

我解决了。点击事件阻止了选择。我不知道为什么,但是当我删除click事件时,它起作用了。 我选择的解决方法是:我在Factory Method中创建了一个计算标志。 如果有人会回答为什么绑定点击事件阻止结果表单反映在DOM上,那将非常有用。

谢谢大家:)

答案 1 :(得分:0)

处理复选框时,您应该使用&#34;已选中&#34;捆绑。 http://knockoutjs.com/documentation/checked-binding.html

这可能会解决您的问题:)

编辑:我很高兴在那里禁食,我看到你正在使用检查绑定。但是你也在使用值绑定。你应该只使用其中一个,在这种情况下检查