Knockout: передача текущего объекта в метод через пользовательский элемент

У меня есть пользовательский элемент html (кнопка), которому я передаю метод. Затем это выполняется привязкой нокаута в пользовательском элементе. Проблема в том, что мне нужен доступ к текущему объекту в массиве при выборе. Я добился этого так:

ko.components.register('custom-element', {
    viewModel: function(params) {

      this.nestedMethod = function (){
        //this line feels dirty
        var parameter = ko.contextFor(arguments[1].target).$parent;
        params.method(parameter);
      }
    }, 
    template:
    '<button data-bind="click: nestedMethod">remove item</button>'
});

Это кажется очень хакерским и потенциально склонным к взлому. Есть ли более приятный способ добиться этого? Вот ссылка на рабочий пример:

http://liveweave.com/w0L5w5


person ViqMontana    schedule 15.04.2015    source источник
comment
Создайте компонент со всем, что вам нужно... Не только с кнопкой. Это будет проще (я думаю) в обслуживании и будет менее хакерским (в любом случае, вы используете клиентские массивы, постарайтесь защитить их, это сложно). Не используйте глобальные массивы (просто используйте их в своей частной области)   -  person Jaime García Pérez    schedule 15.04.2015


Ответы (2)


Поскольку компоненты Knockout предназначены для повторного использования на разных страницах и в моделях представления, они не должны полагаться на модели представления, отличные от собственной модели представления компонента.

Однако вы можете получить доступ к нужным данным, передав текущий bindingContext как часть объекта params.

Например (в вашем HTML):

<custom-element params="method: $parent.removeItem, bindingContext: $context" />

В вашем JS:

viewModel: function(params) {
  this.nestedMethod = function (){
    var bindingContext = params.bindingContext;

    // @access using the following:
    // var rootVm = bindingContext.$root;
    // var currentData = bindingContext.$data;
    // var parentData = bindingContext.$parent;

    var parameter = ko.contextFor(arguments[1].target).$parent;
    params.method(parameter);
  }
},
person haim770    schedule 15.04.2015

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

HTML:

<!-- Note the () in the binding!!! -->
<custom-element params="click: clickHandler()"></custom-element>

JS:

var ParentView = function(message) {
    var self = this;

    self.message = message;

    self.clickHandler = function() {
        return function() {
            alert(self.message);
        }
    }
}

ko.components.register('custom-element', {
    viewModel: function(params) {
        var self = this;

        self.nestedMethod = function() {
            params.click();            
        };
    }, 
    template:  '<button data-bind="click: nestedMethod">remove item</button>'
});

ko.applyBindings(new ParentView("Hello, Knockout!"));

Рабочий JSFiddle

person McCroskey    schedule 15.04.2015