Удалить элемент из списка с помощью Knockout.js - PullRequest
4 голосов
/ 02 января 2012

Я пытаюсь удалить элемент из списка.Я использую knockout.js с плагином отображения.Мой код выглядит так:

Сериализация в Json

@{ var jsonData = new HtmlString(new JavaScriptSerializer().Serialize(Model));}

Шаблон

<script type="text/html" id="imgsList">
    {{each model.Imgs}}
        <div style="float:left; margin: 10px 10px 10px 0;">
            <div><a href="${Filename}"><img src="${Filename}" style="width:100px;"></img></a></div>
            <div data-bind="click: deleteImage">Delete</div>
        </div>
    {{/each}}
</script>

KO JavaScript

<script type="text/javascript">
     $(function() {
        //KO Setup
        var viewModel = { 
            "model": ko.mapping.fromJS(@jsonData),
            "deleteImage" : function(item) {alert(item.Filename + ' deleted.');}
        }

        ko.applyBindings(viewModel);
    });
</script>

HTML

<div data-bind="template: 'imgsList'"></div>

Вопрос

Все работает как положено.Список изображений отображается с кнопками удаления, однако, когда вы нажимаете кнопку элемента. Имя файла не определено.Мысли?

Редактировать: взято из руководства KNockout.js: "При вызове вашего обработчика Knockout будет указывать текущее значение модели в качестве первого параметра. Это особенно полезно, если вы визуализируете некоторый пользовательский интерфейсдля каждого элемента в коллекции, и вам нужно знать, на каком пользовательском интерфейсе был выполнен щелчок. "

Похоже, я не получаю ожидаемый объект Img.Я не знаю, что я возвращаюсь!

Ответы [ 2 ]

7 голосов
/ 03 января 2012

Я заметил, что здесь есть пример того, как это сделать:

http://blog.stevensanderson.com/2011/12/21/knockout-2-0-0-released/

Проверьте 4. Более чистая обработка событий раздел, где Стив показывает пример удаления элемента из списка.

<h3>Products</h3>

<ul data-bind="foreach: products">
    <li>
        <strong data-bind="text: name"></strong>
        <button data-bind="click: $parent.removeProduct">Delete</button>
    </li>
</ul>

Javascript:

    function appViewModel() {
        var self = this;
        self.products = ko.observableArray([
            { name: "XBox" },
            { name: "PlayStation" },
            { name: "Banana" },
            { name: "Wii" }
        ]);

        self.removeProduct = function(product) {
            self.products.remove(product);   
        }
    };

ko.applyBindings(new appViewModel());

Но учтите, что приведенный выше пример относится к KnockoutJS 2.0, который является последней версией.

6 голосов
/ 03 января 2012

Когда вы используете {{each}} синтаксис в шаблонах jQuery, контекст данных - это то, с чем связан весь шаблон.В вашем случае это вся модель представления.

Несколько опций:

1 - вы можете использовать свой текущий код и передать элемент, который «вам нравится», в функцию, например (http://jsfiddle.net/rniemeyer/qB9tp/1/):

<div data-bind="click: function() { $root.deleteImage($value); }">Delete</div>

Использование анонимной функции в привязке данных довольно уродливо.Есть лучшие варианты.

2 - вы можете использовать параметр foreach привязки шаблона, который работает с шаблонами jQuery и более эффективен, чем {{each}}, как (http://jsfiddle.net/rniemeyer/qB9tp/2/):

<script type="text/html" id="imgsList">
    <div style="float:left; margin: 10px 10px 10px 0;">
        <div>
            <a href="${Filename}">${Filename}</a>
        </div>
        <div data-bind="click: $root.deleteImage">Delete</div>
    </div>
</script>

<div data-bind="template: { name: 'imgsList', foreach: model.Imgs }"></div>

Теперь контекст шаблона - это отдельный объект изображения, и вызов $root.deleteImage передаст его в качестве первого аргумента.

3 - Поскольку плагин jQuery Templatesустарел, а Knockout теперь поддерживает собственные шаблоны, вы можете выбрать удаление зависимости от плагина jQuery Templates.Вы по-прежнему можете использовать именованный шаблон (просто нужно заменить любой синтаксис шаблонов jQuery на атрибуты привязки данных), например: http://jsfiddle.net/rniemeyer/qB9tp/3/ или даже удалить шаблон и просто использовать привязку потока управления foreach, например: http://jsfiddle.net/rniemeyer/qB9tp/4/

<div data-bind="foreach: model.Imgs">
    <div style="float:left; margin: 10px 10px 10px 0;">
        <div>
            <a data-bind="text: Filename, attr: { href: Filename }"></a>
        </div>
        <div data-bind="click: $root.deleteImage">Delete</div>
    </div>
</div>

4 - Хотя я предпочитаю вариант № 3, вы можете даже выбрать использование делегирования события и подключить «живой» обработчик, например: http://jsfiddle.net/rniemeyer/qB9tp/5/

$("#main").on("click", ".del", function() {
   var data = ko.dataFor(this);
   viewModel.deleteImage(data); 
});

Этоможет быть особенно полезным, если вы будете подключать большое количество одинаковых обработчиков через привязку click (как в сетке).

...