开发者

Retrieving data bound object

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);
                }
            }
        });
    }
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜