Cyclical observable with knockoutjs

2019-09-05 03:49发布

I have a view which presents as seen in the following screen grab:

enter image description here

On clicking an item from the Views column, the Available Columns list is populated. When the user then clicks a different item from the Views list, the Available Columns list needs to be reset and populated with columns relevant to the newly selected View

In my knockout view model I have the following subscriptions and computed:

self.columnsToAdd.subscribe(function (items) {
    var viewIndex = findViewIndex(self.selectedView().ViewId);
    //delete columns from the selected view then add in those that are in the 
    //columnsToAdd list
    data.Users[0].Views[viewIndex].VisibleColumns.length = 0;
    for (i = 0; i < items.length; i++) {
        data.Users[0].Views[viewIndex].VisibleColumns.push(view = {ColumnId:items[i].ColumnId, Heading:items[i].Heading});
    }
});

self.selectedView.subscribe(function (item) {
    //clear columnsToAdd then re-populate
    //this line is causing data.Users[0].Views[0].VisibleColumns to be reset
    //because it triggers the columnsToAdd.Subscribe
    self.columnsToAdd([]); 
    var view = getById(self.views, item.ViewId);
    for (i = 0; i < view.VisibleColumns.length; i++) {
        self.columnsToAdd.push(view.VisibleColumns[i]);
    }
});

self.allColumns = ko.computed(function () {
    var view = getById(self.views, self.selectedView().ViewId);
    return view ? ko.utils.arrayMap(view.AllColumns, function (item) {
        return {
            ColumnId: item.Id,
            Heading: item.Heading
        };
    }) : [];
}, this);

As can be seen in my code comments, the problem is with the subscription of the selectedView observable. This is bound to the selected item of the Views list. When this changes I need to clear down the Available Columns list but this then causes the subscription of the bound observable array to fire which then clears out the VisibleColumns observable array, needed by the selectedView subscription.

Is there a standard pattern to use to solve such problems with knockoutjs?

1条回答
Animai°情兽
2楼-- · 2019-09-05 03:57

My solution was to remove the subscription on columnsToAdd observable array. Instead, I update the backing view model's VisibleColumns collections of the Views collections within the events for the Add and Remove buttons:

self.addColumn = function () {
        if (self.columnsToAdd().indexOf(self.selectedAvailableColumn()) < 0) {
            self.columnsToAdd.push(self.selectedAvailableColumn());
            data.Users[0].Views[self.viewIndex].VisibleColumns.push(self.selectedAvailableColumn())
        }
    };

    self.removeColumn = function () {
        self.columnsToAdd.remove(self.selectedColumnToRemove());
        data.Users[0].Views[self.viewIndex].VisibleColumns.pop(self.selectedAvailableColumn())
    };
查看更多
登录 后发表回答