Knockout Add and Edit observableArray Conflict

笑着哭i 提交于 2019-12-25 02:54:03

问题


I have an observableArray which is displayed in a table using foreach binding where values are displayed inside textboxes. Now what I want to do is to add an edit link on each row which enables/disables the readonly state of the corresponding textbox in its row. I can do it, but the way I did it messed up my add new line (push) functionality.

Here is a fiddle of my code.

Try to delete a line then add it again by selecting it in the dropdown list, the edit link disappears as well as the value.

Any help will be greatly appreciated! Thank you.

So here's my HTML:

<table class="input-group" >
    <tbody data-bind="foreach: loanDeductions">
        <tr>
            <td><strong data-bind='text: deductionName'></strong></td>
            <td><input class="deductionCode form-control" style="text-align: right" data-bind='value: amount, valueUpdate: "afterkeydown", attr: { "readonly": getreadonlyState() }' /></td>
            <td><a href='#' data-bind='click: $parent.removeLine'>Delete</a></td>
            <td><a href="javascript:void(0);" data-bind="click: $parent.readonly"><span data-bind="text: linkText"></span></a></td>
        </tr>
    </tbody>        
</table>
<table>
    <tr>
        <td colspan="3"><select data-bind="options: loanDeductionsList(), optionsText: 'deductionName', optionsCaption: 'Choose a deduction..', value: selectedDeduction"></select></td>
    </tr>
</table>

Now here is my script:

var deductionLine = function (deductionID, deductionName, amount) {
    self = this;
    self.deductionID = ko.observable(deductionID);
    self.deductionName = ko.observable(deductionName);
    self.amount = ko.observable(formatCurrency(amount));
    self.getreadonlyState = ko.observable('readonly');
    self.linkText = ko.computed(function () {
        return this.getreadonlyState() == 'readonly' ? "Edit" : "Stop Edit";
    }, self);
};

var deductionList = function (deductionID, deductionName, amount) {
    self = this;
    self.deductionID = ko.observable(deductionID);
    self.deductionName = ko.observable(deductionName);
    self.amount = ko.observable(formatCurrency(amount));
};

function LoanDeductions(deductions) {
    var self = this;
    self.loanDeductions = ko.observableArray(ko.utils.arrayMap(deductions, function (deduction) {
        return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
    }));
    self.loanDeductionsList = ko.observableArray(ko.utils.arrayMap(deductions, function (deduction) {
        return new deductionList(deduction.deductionID, deduction.deductionName, deduction.amount)
    }));

    self.selectedDeduction = ko.observable();

    //edit link

    self.readonly = function () {
        if (BossBaU) {
            if (this.getreadonlyState()) {
                this.getreadonlyState(undefined);
            }
            else {
                this.getreadonlyState('readonly');
            }
        }
        else alert('Access denied!');
    }

    // adds deduction 
    self.selectedDeduction.subscribe(function (data) {
        var match = ko.utils.arrayFirst(self.loanDeductions(), function (deduction) {
            return deduction.deductionID() === data.deductionID();
        });
        if (match) {
            alert(data.deductionName() + ' already exists!');
            self.showAddDeduc(false);
        } else {
            self.loanDeductions.push({
                deductionID: data.deductionID,
                deductionName: data.deductionName,
                amount: data.amount,
            });
            self.showAddDeduc(false);
        }
    });

    //delete deduction
    self.removeLine = function (line) { self.loanDeductions.remove(line) };

};

var viewModel = new LoanDeductions(@Html.Raw(Model.CRefLoansDeductions2.ToJson()));
$(document).ready(function () {
    ko.applyBindings(viewModel);
});

回答1:


In the subscribe handler, self.selectedDeduction.subscribe, you're adding an object to the list of loanDeductions when you should be adding a new instance of deductionLine just as you do when you declare self.loanDeductions.

Or to put it another way, self.loadDeductions is an observableArray of deductionLine instances, to which you then add an object with three properties.

Change that subscribe handler to push a new deductionLine(...) and you'll see the difference.




回答2:


I found the cause of the problem, I had to mirror every changes I made with my observableArray to my list.

var deductionLine = function (deductionID, deductionName, amount) {
    self = this;
    self.deductionID = ko.observable(deductionID);
    self.deductionName = ko.observable(deductionName);
    self.amount = ko.observable(amount);
    self.getreadonlyState = ko.observable('readonly');
    self.linkText = ko.computed(function () {
        return this.getreadonlyState() == 'readonly' ? "Edit" : "Stop Edit";
    }, self);
};

var deductionList = function (deductionID, deductionName, amount) {
    self = this;
    self.deductionID = ko.observable(deductionID);
    self.deductionName = ko.observable(deductionName);
    self.amount = ko.observable(amount);
    self.getreadonlyState = ko.observable('readonly');
    self.linkText = ko.computed(function () {
        return this.getreadonlyState() == 'readonly' ? "Edit" : "Stop Edit";
    }, self);
};

Here's the fiddle in case anyone bump into a similar issue.



来源:https://stackoverflow.com/questions/30066669/knockout-add-and-edit-observablearray-conflict

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!