Reputation: 27
knockout is awesome....at the same time i feel kinda frustrated by the gotchas....:|
heres my code
<html>
<head>
@using MvcJqGrid;
@using System.IO;
@using System.Web.Mvc;
@using System.Web.Script.Serialization;
@{
Layout = "";
JavaScriptSerializer theSerializer = new JavaScriptSerializer();
}
<link rel="Stylesheet" type="text/css" href="Content/themes/base/jquery-ui.css" />
<link rel="Stylesheet" type="text/css" href="Content/themes/base/jquery.ui.base.css" />
<link rel="Stylesheet" type="text/css" href="Content/themes/base/jquery.ui.theme.css" />
<link rel="Stylesheet" type="text/css" href="Content/ui.jqgrid.css" />
<script type="text/javascript" src="Scripts/modernizr.custom.05850.js"></script>
<script type="text/javascript" src="Scripts/jquery-1.7.2.js" > </script>
<script type="text/javascript" src="Scripts/jquery-ui-1.8.19.js"> </script>
<script type="text/javascript" src="Scripts/grid.locale-en.js" ></script>
<script type="text/javascript" src="Scripts/jquery.jqGrid.min.js"></script>
<script type="text/javascript" src="Scripts/json2.min.js"></script>
<script type="text/javascript" src="Scripts/knockout-2.1.0.js"></script>
<script type="text/javascript" src="Scripts/knockout.mapping-latest.js"></script>
<script type="text/javascript" src="Scripts/linq.min.js"></script>
</head>
<body>
<!-- This is a *view* - HTML markup that defines the appearance of your UI -->
<p>View Name: <input data-bind="value: Name " /></p>
<p>No Of Results: <input data-bind="value: noOfResultsPerPage "/></p>
<p id='filterEnable'>
click me to invoke ajax service
</p>
<input type=text value="tester" id="testInput" />
<input type=text value='test' data-bind='value:myComputedFilterExpression' id="linqTester" />
<p id='myLabel' >
container
</p>
<p id='addFilterExpression' >add Filter</p>
<table data-bind='visible: filterArray().length > 0'>
<thead>
<tr>
<th>filterExpression</th>
<th />
<th />
</tr>
</thead>
<tbody data-bind='foreach: filterArray'>
<tr>
<td data-bind"text :theExpression,value :theExpression">
Where <select class='required' data-bind="options: $root.options, optionsCaption: 'Select...'" />
<input type='text' id='uifix' style='display:none' />
<select class='required' data-bind="options: $root.filterExpressionValues, optionsCaption: 'Select...'" />
<input type='text' id='inputValue' />
<select class='required' data-bind='options: $root.queryOptions, optionsCaption: "Select..."' />
</td>
<td><a href='#' data-bind='click: $root.removeFilter'>Delete</a></td>
<td><a href='#' data-bind='click: $root.addFilter'>Add</a></td>
</tr>
</tbody>
</table>
<script type="text/javascript">
$(function () {
var viewModel = null;
var [email protected](PseudoSharepointView.getAllVariables());
function FilterExpression()
{
this.theExpression="";
}
function Success(data, status) {
$("#myLabel").html(data.d);
}
function Error(request, status, error) {
$("#myLabel").html(request.statusText);
}
$('#filterEnable').click(function () {
CallService();
});
var [email protected](PseudoSharepointView.getAView());
// Activates knockout.js
viewModel = ko.mapping.fromJS(test);
viewModel.options=myOptions;
viewModel.queryOptions=["and","or"];
[email protected](theSerializer.Serialize(PseudoSharepointView.SharepointColumn.FilterExpressionValues));
var test=ko.mapping.toJS(viewModel);
$("#testInput").val(JSON.stringify(test));
viewModel.filterArray=ko.observableArray([new FilterExpression()]);
viewModel.myComputedFilterExpression = ko.computed(function() {
return Enumerable.From((viewModel.filterArray())).Select('$.theExpression').Aggregate("(a,b)=>a+''+b");
});
// Operations
viewModel.addFilter = function() {
viewModel.filterArray.push(new FilterExpression());
};
viewModel.removeFilter = function(filter) {
viewModel.filterArray.remove(filter) ;
};
ko.applyBindings(viewModel);
$('#addFilterExpression').click(function () {
testArray= new Array();
testArray[0]= new FilterExpression();
testArray[0].theExpression="1";
testArray[1]= new FilterExpression();
testArray[1].theExpression="2";
var test=Enumerable.From((viewModel.filterArray())).Select('$.theExpression').Aggregate("(a,b)=>a+''+b");
$('#linqTester').val(test);
});
function CallService() {
$.ajax({
type: "POST",
url: "myMethodsRepository.asmx/HelloWorld",
data: "{viewValue:'"+JSON.stringify(ko.mapping.toJS(viewModel))+"'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: Success,
error: Error
});
}
});
</script>
</body>
</html>
my questions are as follows
1) is there a thingy that has to be done for two way binding to work....cuz the ui updation sure does happen but the actual value doesnt ummm update itself... obviously i am missing out on something over here
2) my computed function
viewModel.myComputedFilterExpression = ko.computed(function() {
return Enumerable.From((viewModel.filterArray())).Select('$.theExpression').Aggregate("(a,b)=>a+''+b");
});
doesnt seem to work as the variable isnt updating itself
i used this debugging aid
<input type=text value='test' data-bind='value:myFilterExpression' id="linqTester" />
hoping that u knw the required string expression wud be constructed from the array
i need a basic /noob friendly explanation of two way binding to an observable array....if anyone is willin to show it with my current piece of code, god bless them...:)
Upvotes: 1
Views: 3362
Reputation: 15984
The problem is that myComputedFilterExpression
is a read-only computed function that is returning an enumerable expression. What did you expect to get updated by your value binding?
To make a computed obervable read-write you need to define it like so. Also covered in the docs here under writable computed observables.
this.fullName = ko.computed({
read: function () {
return this.firstName() + " " + this.lastName();
},
write: function (value) {
var lastSpacePos = value.lastIndexOf(" ");
if (lastSpacePos > 0) { // Ignore values with no space character
this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
}
},
owner: this
});
When the value binding updates the computed, you receive the new value in the define write function and it's your job to map that to some underlying value.
Hope this helps
Upvotes: 8