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.de开发者_开发知识库scriptive = 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:
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
init: function(element, valueAccessor) {
var list = valueAccessor();
$(element).sortable({
update: function(event, ui) {
//retrieve our actual data item
var item = ui.item.tmplItem().data;
//figure out its new position
var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
//remove the item and add it back in the right spot
if (position >= 0) {
list.remove(item);
list.splice(position, 0, item);
}
}
});
}
};
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 tmplItem
line with the new ko.dataFor
method available in 1.3:
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
init: function(element, valueAccessor) {
var list = valueAccessor();
$(element).sortable({
update: function(event, ui) {
//retrieve our actual data item
var item = ko.dataFor(ui.item[0]);
//figure out its new position
var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
//remove the item and add it back in the right spot
if (position >= 0) {
list.remove(item);
list.splice(position, 0, item);
}
}
});
}
};
精彩评论