Reputation: 8711
I am trying to figure out knockoutjs (verion 3.4) with ASP.net MVC4
I have the following view model:
function ViewModel(data) {
var self = this;
self.filteredColumnsArray;
var viewsArray = buildSimpleViewsArray(data.AllViews);
self.views = ko.observableArray(viewsArray);
self.selectedView = ko.observable(viewsArray[0]);
self.newView = ko.observable("");
var columnsArray = ko.observableArray(data.AllColumns);
self.filteredColumns = ko.observableArray(self.filteredColumnsArray);
self.columnsToAdd = ko.observableArray();
self.selectedView.subscribe(function () {
self.filteredColumnsArray = ko.utils.arrayFilter(columnsArray(), function (column) {
return column.ViewId === getViewId(self.selectedView());
});
self.filteredColumns = ko.observableArray(self.filteredColumnsArray);
});
function getViewId(viewName) {
var id;
var index;
for (index = 0; index < data.AllViews.length; ++index)
{
if (data.AllViews[index].Name === viewName) {
id = data.AllViews[index].ViewId;
}
}
return id;
};
function buildSimpleViewsArray(objectArray) {
var simpleArray = new Array;
for (var o in objectArray) {
simpleArray.push(objectArray[o].Name);
}
return simpleArray;
}
function buildSimpleColumnsArray(objectArray) {
var simpleArray = new Array;
for (var o in objectArray) {
simpleArray.push(objectArray[o].Heading);
}
return simpleArray;
}
self.addView = function () {
if ((self.newView() != "") && (self.views.indexOf(self.newView()) < 0)) // Prevent blanks and duplicates
self.views.push(self.newView());
self.newView(""); // Clear the text box
};
self.removeSelected = function () {
this.views.remove(self.selectedView);
this.selectedView = "";
};
self.saveToDatabase = function () {
this.views.remove(self.selectedView);
this.selectedView = "";
};
};
and this view:
@model TVS.ESB.BamPortal.Website.Models.UserPrefsViewModel
@using System.Web.Script.Serialization
@{
ViewBag.Title = "User Preferences";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>@ViewBag.Title</h2>
@{ string data = new JavaScriptSerializer().Serialize(Model); }
<div id="ViewsAndColumns" class="container">
<div class="row">
<div id="Views" class="col-md-6 pull-left">
<span class="label-primary">Views</span>
<br />
<table>
<tr>
<td>
<span>New View:</span>
</td>
<td>
<input style="width:100px" class="input-sm" data-bind='value:newView, valueUpdate: "afterkeydown"' />
<button class="btn-default" data-bind="click:addView, enable:newView().length > 0">Add View</button>
</td>
</tr>
<tr>
<td>
<span>Views:</span>
</td>
<td>
<select style="width:100px" size="5" data-bind="options:views, value:selectedView"> </select>
<button class="btn-default" data-bind="click:removeSelected">Remove</button>
</td>
</tr>
<tr>
<td>
<button class="btn-danger" data-bind="click:saveToDatabase">Save to Database</button>
</td>
</tr>
</table>
</div>
<div id="Columns" class="col-md-6 pull-right">
<span class="label-primary">Columns</span>
<br />
<table>
<tr>
<td>
@*<select multiple="multiple" data-bind="options:filteredColumns, selectedOptions:columnsToAdd"></select>*@
<select multiple="multiple" data-bind="options:filteredColumns"></select>
</td>
</tr>
</table>
</div>
</div>
</div>
@section Scripts {
<script src="~/KnockoutVM/UserPrefs.js"></script>
<script type="text/javascript">
var vm = new ViewModel(@Html.Raw(data));
ko.applyBindings(vm, document.getElementById("UserPrefsDiv"));
</script>
}
The VM receives this data:
{
"ViewId": 0,
"Name": null,
"AllColumns": [
{
"ColumnId": 5,
"ViewId": 5,
"Heading": "ErpColumn1"
},
{
"ColumnId": 6,
"ViewId": 5,
"Heading": "ErpColumn2"
},
{
"ColumnId": 7,
"ViewId": 6,
"Heading": "CceColumn1"
},
{
"ColumnId": 8,
"ViewId": 6,
"Heading": "CceColumn2"
}
],
"VisibleColumns": [],
"AllViews": [
{
"ViewId": 5,
"Name": "erp",
"Columns": [
{
"ColumnId": 5,
"ViewId": 5,
"Heading": "ErpColumn1"
},
{
"ColumnId": 6,
"ViewId": 5,
"Heading": "ErpColumn2"
}
]
},
{
"ViewId": 6,
"Name": "cce",
"Columns": [
{
"ColumnId": 7,
"ViewId": 6,
"Heading": "CceColumn1"
},
{
"ColumnId": 8,
"ViewId": 6,
"Heading": "CceColumn2"
}
]
}
]
}
In my view their are 2 multi-line selection boxes, Views and Columns. When the user select a row from the Views list I'd like the Columns list to display only columns with the appropriate view Id.
I think I almost have this working. Using the Chrome dev tools, I placed a breakpoint in the selectedView.subscribe function and I could see that filteredColumnsArray is populated correctly. This is then assigned to the observeable array filteredColumns which is bound to the second select list in the view. My problems is, the second list is not refreshed as I'd expect.
Any help would be appreciated.
Upvotes: 1
Views: 48
Reputation: 4222
The problem is probably because you are creating a new ko.observableArray()
to filteredColumns
and this is not binded to the view, insted to change the "value" of the property change the value of the ko.observable
.
Ex Insted this:
var x = ko.observable("1st value");
x = ko.observable("2nd value");
Do this:
var x = ko.observable("1st value");
x("2nd value");
Try this at subscribe
of selectedView
:
self.selectedView.subscribe(function () {
var filtered = ko.utils.arrayFilter(columnsArray(), function (column) {
return column.ViewId === getViewId(self.selectedView());
});
self.filteredColumns(filtered)
});
Upvotes: 1