Пользовательская привязка свойства элемента в наблюдаемом массиве, как получить доступ к элементу?

Фон

У меня есть наблюдаемый массив GalleryImages, где каждый элемент имеет свойства, связанные с изображением (имя, описание, путь и т. Д.). Нокаут foreach выполняет итерацию по массиву объектов для создания диапазонов, содержащих изображение, имя и описание. Если пользователь щелкает имя или описание изображения, он может отредактировать значение и нажать «Сохранить/отменить», чтобы обновить модель представления.

Вопрос

Учитывая, что пользовательская привязка привязана к свойству элемента в наблюдаемом массиве, как получить доступ к элементу, которому принадлежит свойство, внутри определения пользовательской привязки? Я хотел бы получить только что отредактированный элемент и передать его функции, которая будет обновлять сервер с изменениями.

Я попытался просмотреть allBindingsAccessor(), но он возвращает свойство элемента, а не сам элемент.

HTML

<div data-bind="foreach: GalleryImages">
    <span class="img">
        <a data-bind="attr: { href: URL}">
            <img data-bind="attr: { src: URL}"/>
        </a>
        <div>
            <h4 data-bind="text: ItemName"></h4>
            <input type="text" data-bind="clickEditor: ItemName"/>
        </div>
        <div>
            <span data-bind="text: Description"></span>
            <textarea data-bind="clickEditor: Description"></textarea>
        </div>
    </span>
</div>

knockoutJS Вот пользовательская привязка для clickEditor.

ko.bindingHandlers.clickEditor = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var $element = $(element).hide();
        var $text = $element.prev();
        var $parent = $element.parent();

        var $editElements = $("<div class='editConfirm'> \
            <button class='saveEdit' type='button'>Save</button> \
            <button class='cancelEdit' type='button'>Cancel</button> \
        </div><span class='placeHolder'></span>").hide().insertAfter($element).add($element);

        var _toggle = function (edit) {
            $text[edit ? 'hide' : 'show']();
            $editElements[edit ? 'show' : 'hide']();
        };

        $text.click(function (e) {
            _toggle(true);              
        });

        $editElements.find('.saveEdit').click(function () {
            _toggle(false);

            //update clientside viewModel
            valueAccessor()($element.val());

            // this var needs to contain the item in the observable array that was updated
            var imageUpdated;

            //update server with changes
            saveModel(imageUpdated);
        });

        $editElements.find('.cancelEdit').click(function () {
            _toggle(false);
            $(element).val(ko.utils.unwrapObservable(valueAccessor()));
        });
    }
    , update: function (element, valueAccessor) {
        $(element).val(ko.utils.unwrapObservable(valueAccessor()));
    }
};

person Jerry    schedule 13.04.2012    source источник


Ответы (1)


Из атрибута привязки данных вы можете получить доступ к данным для текущей области, используя $data.

Если вы находитесь в привязке, то аргумент viewModel (4-й аргумент) на самом деле является текущими данными, с которыми выполняется привязка (так что в этом случае ваш элемент массива). На самом деле в KO 2.0 также есть 5-й аргумент, который является контекстом. Контекст содержит $data, $parent, $parents и $root.

Итак, лучше всего использовать аргумент viewModel в привязке.

person RP Niemeyer    schedule 13.04.2012
comment
Спасибо, Райан. Я несколько раз просматривал документацию по custom-bindings, но не читал внимательно Описание ViewModel. Я предположил, что это относится ко всей модели представления, а не к отдельному элементу, как указано в описании. - person Jerry; 16.04.2012
comment
Я думаю, что мы должны изменить имя параметра viewModel на data или что-то в этом роде. Вообще непонятно, что это не относится к модели корневого представления. - person RP Niemeyer; 16.04.2012