Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update observableArray item on edit

Tags:

knockout.js

jsFiddle example


I have an observableArray of selectable items (in a table). What I'm trying to do is open a modal on click of the table row, populate the modal with the item details, allow editing of the item and then save the changes - reflecting the updated item in the observableArray. I've got everything else working so far, but can't seem to get the array item to update.

So far I've tried:

  • Making every item in the observableArray an observable
  • using .replace on the array to update the item - this does work, but it just feels wrong
  • posting back the updated item, applying it to the database and rebinding the array - although this works, doesn't this defeat the point of KnockoutJS?

I've provided a jsFiddle link above that demonstrates what I'm trying to achieve.

View model and initialization

Feel free to make any suggestions on how I'm initializing self.selectItem I'm currently in the learning stage of KnockoutJS, and doing so by playing around with mock projects so I'm open to all constructive criticism.

var items = [{
    Id: 1,
    Text: 'First item'
}, {
    Id: 2,
    Text: 'Second item'
}];

var viewModel = function (items) {
    var self = this;
    self.items = ko.observableArray(items);
    self.selectedItemId = ko.observable();
    self.item = ko.observable();
    self.selectItem = function (item) {
        for (var i = 0; i < self.items().length; i++) {
            if (self.items()[i].Id === self.selectedItemId()) {
                self.item(self.items()[i]);
                break;
            }
        }
    };
};

ko.applyBindings(new viewModel(items));

Markup bindings

<select data-bind="options: items, optionsCaption: 'Select...', optionsText: 'Text', optionsValue: 'Id', value: selectedItemId, event: { change: selectItem }"></select>
<div data-bind="if: item">
    <input type="text" data-bind="value: item().Text" />
</div>
<table>
    <thead>
        <tr>
            <th>Text</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr>
            <td data-bind="text: $data.Text"></td>
        </tr>
    </tbody>
</table>
like image 627
Paul Aldred-Bann Avatar asked Jul 16 '13 07:07

Paul Aldred-Bann


People also ask

What is ko ObservableArray?

An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.

What is observable array?

ObservableArray is an array that allows listeners to track changes when they occur. In order to track changes, the internal array is encapsulated and there is no direct access available from the outside. Bulk operations are supported but they always do a copy of the data range.


2 Answers

I have create a new jsFiddle example with an update of items when you change the 'Text' property.

Your problem was the 'items' variable. If you want to update items properties, you have to make them observable :

var observableItems = [
    new ItemViewModel(1, "First item"),
    new ItemViewModel(2, "Second item")
];

function ItemViewModel(id, text){
    var self = this;
    self.Id = ko.observable(id);
    self.Text = ko.observable(text);
}

Hope it helps !

like image 111
Joffrey Kern Avatar answered Nov 15 '22 06:11

Joffrey Kern


Your code work fine. All what you need is to update your items array to have it's property Text to be observable

var items = [{
    Id: 1,
    Text: ko.observable('First item')
}, {
    Id: 2,
    Text: ko.observable('Second item')
}];

And i add small code to check if the selected option is "Select..." then clear the item to hide the input text.

kindly check my Working DEMO

like image 26
ebram khalil Avatar answered Nov 15 '22 08:11

ebram khalil