1
votes

I have observable arrays which are bound to the html fields on the UI.

However, the changes to those fields on the UI are not reflected in the viewmodel because as per the Knockout documentation, An observableArray tracks which objects are in the array, not the state of those objects.

The code looks as below:

var RewardMissionModel = function () {
    var self = this;
    self.achievementID = ko.observable();
    self.rewardAsset = ko.observable();
    self.rewards = ko.observableArray([new Reward("Points", "Qty", "", "Item", "")]);

    self.isDirty = false;

    //Add reward
    self.addReward = function () {
        //var self = this;
        var tempRewardType = "Points";
        self.rewards.push(new Reward(tempRewardType, "Qty", "", "Item", "", 0));
    };

    //Remove reward
    self.removeReward = function (reward) {
        if (self.rewards().length > 1)
            self.rewards.remove(reward);
    };
    //------------------------------------------------------------------------------
};

function Reward(rewardType, quantityLabel, rewardQuantity, itemLabel, item, itemID) {
    var self = this;
    //self.viewModel = viewModel;
    self.rewardTypes = ["Points", "Coins", "Items"];    
    self.rewardType = ko.observable(rewardType);
    self.itemLabel = ko.observable(itemLabel);
    self.itemText = ko.observable(item);
    self.quantityLabel = ko.observable(quantityLabel);
    self.rewardQuantity = ko.observable(rewardQuantity);
    this.selectedRewardType = ko.observable(rewardType);
    self.isItemType = function (selectedRewardType) {
        return selectedRewardType === this.selectedRewardType();
    }

    self.itemID = ko.observable(itemID);

}

HTML code:

<div data-bind="template: { name: 'rewards-template', foreach: rewards }"></div>
                <script type="text/html" id="rewards-template">
                    <span style="margin-left:30px">Reward Type</span>
                    <select class="dropdown" data-bind="options: rewardTypes, value: selectedRewardType"></select>
                    <span data-bind="text: itemLabel, visible: isItemType('Items')"></span>

The viewmodel dirty flag gets set when i add or remove objects into the observable array, but when i modify on the UI it is not considered.

One of the approach could be to put a normal array within an observable.

Is there any code example to illustate this or any better approach?

Please help.

2

2 Answers

0
votes

I think the best way to make the properties of your observable array object act as observable is to make them also observable so that you are creating observable array that contains also observable. For example::

    var viewModel = {
    accounts: ko.observableArray([]),
    init: function () {
        this.accounts.push({
            Property1: ko.observable("some value"),
            Property2: ko.observable("some value"),
            Property3: ko.observable("some value")
            });
        }
    };

kindly check this question, i think it's what you are looking for

Updating of object inside observable array is done but changes are not coming on browser

0
votes
function MyObject(val1, val2)
{
   this.firstProperty = ko.observable(val1);  
   this.secondProperty = ko.observable(val1);
}  

var myViewModel = new function()  
{  
   var self = this;
   self.values = ko.observableArray([]);  
   self.values.push(new MyObject("value11", "value12"));  
   self.values.push(new MyObject("value21", "value22"));
}