I created a ViewModel which has an observable property. I bind this array to an ul HTML element, like this:
<ul id="sortable"
data-bind="template: { name: 'parameterTemplate',
foreach: parameters },
visible: parameters().length > 0"
style="width: 100%">
</ul>
My template is this:
<script type="text/html" id="parameterTemplate">
<li class="ui-state-default parameterItem">
<input type="checkbox" data-bind="checked: isRequired" />
Name:
<input data-bind="value: name " />
Type:
<input data-bind="value: type " />
Size:
<input data-bind="value: size " />
<a href="#" data-bind="click: remove">Delete</a>
</li>
</script>
I’m using the draggable and sortable resources of jQuery to reorder the elements of the list. This means that when the users changes the order of the element, obviously ko databind is not altered, for jQuery does not know knockout exists.
It so happens that I want my parameters to be saved in the same order the user configured. So my approach was to select al the li HTML elements via jQuery, getting an array ( var items = $(".parameterItem");) . How can I get , for each item in items, the databound knockout element, associated with the li HTML element?
Is it possible?
My View Model:
function parameter(parameterName, parameterType, parameterSize, descriptive, defaultValue, isRequired, ownerViewModel) {
this.name = ko.observable(parameterName);
this.type = ko.observable(parameterType);
this.size = ko.observable(parameterSize);
this.label = ko.observable(parameterName);
this.descriptive = ko.observable(descriptive);
this.defaultValue = ko.observable(defaultValue);
this.descriptive = ko.observable(descriptive);
this.isRequired = ko.observable(isRequired);
this.ownerViewModel = ownerViewModel;
this.remove = function () {
ownerViewModel.parameters.remove(this)
};
}
function excelLoaderViewModel() {
this.parameters = ko.observableArray([]);
this.newParameterName = ko.observable();
this.newParameterType = ko.observable();
this.newParameterSize = ko.observable();
this.newParameterDescriptive = ko.observable();
this.newParameterIsRequired = ko.observable();
this.newParameterDefaultValue = ko.observable();
this.systemName = ko.observable();
this.addParameter = function () {
this.parameters.push(
new parameter(
this.newParameterName()
, this.newParameterType()
, this.newParameterSize()
, this.newParameterDescriptive()
, this.newParameterDefaultValue()
, this.newParameterIsRequired()
, this));
this.newParameterName("");
this.newParameterType("");
this.newParameterSize("");
this.newParameterIsRequired(false);
this.newParameterDefaultValue("");
}
var myVM = new excelLoaderViewModel();
ko.applyBindings(myVM);
Your best bet is to use a custom binding to keep your observableArray in sync with your elements as they are dragged/dropped.
Here is a post that I wrote about it a while ago.
Here is a custom binding that works with jQuery Templates:
Here is a sample of it in use: http://jsfiddle.net/rniemeyer/vgXNX/
If you are using it with Knockout 1.3 beta without jQuery Templates (or with), then you can replace the
tmplItemline with the newko.dataFormethod available in 1.3: