2013-03-06 1 views
13

В моем представлении модели у меня есть прототипы методов, где этот контекст - это элемент для каждого, а не для реальной модели. Как мне это достичь?

<button data-bind="click: $parent.methodThatNeedsAccesToTheParentViewModel">Edit</button> 

ViewModel:

ViewModel.prototype.methodThatNeedsAccesToTheParentViewModel= function() { 
     this = duff //this is the item in the foreach, not the real parent 
    }; 

Идеи?

+0

Вы спрашиваете, как на самом деле получить * это * переменная в методе, чтобы указать на * ViewModel * например? Или что-то другое? – Grim

+0

@Grim the first :) – FutuToad

ответ

13

Не передавайте функцию непосредственно привязке кликов, оберните ее анонимной функцией, чтобы вызвать ее в контексте вашего вид модель:

<button data-bind="click: function() { $parent.methodThatNeedsAccesToTheParentViewModel() }">Edit</button> 

таким образом, когда связывание активировано, он будет использовать $ родителя в контексте вызова - т.е. это

стоит отметить, (так как мы не можем видеть структуру привязки файлов), что $ parent переменная будет ссылаться на привязку , предшествующую итерации текущего элемента, что не обязательно является родительским элементом элемента в графе объектов.

Edit: я пропускал некоторые выше скобку ...

Edit 2: это работает в связи с тем, как связывание будет решена. Когда привязка применяется нокаутом, выражение разрешается и должно оцениваться с помощью функции (и поэтому, когда вы привязываетесь непосредственно к функции, нет необходимости в скобках). Затем эта функция вызывается, когда активируется привязка кликов.

Но вот загвоздка, так как это ключевое слово в прототипных JavaScript не связан владельцем функции (т.е. там, где она определена), а на том, как она называется (как объяснено лучше в mozilla documentation) в этом случае нокаут вызывает функцию не через объект, который ее владеет (что правильно привязывает к этому оператору), но привязывает его явно к его текущему контексту привязки (так как он не может знать, какой экземпляр функция была первоначально взята). Вы можете повторить это поведение, получая ссылку на вашу функцию, а затем связывая его с другим объектом во время вызова - пример:

A = function() { 
    this.name = "foo"; 
}; 
A.prototype.getName = function() { return this.name; }; 

a = new A(); 

console.log(a.getName()); // should log "foo" as expected 

f = a.getName; // now f contains a reference to the function 

console.log(f()); // this call the function in the current scope - most likely the window, and return nothing 

b = new Object(); // another generic object - suppose this is knockout binding context 

console.log(f.call(b)); // this bind the call explicitly to b, but since b has no name property, nothing is returned again 

console.log(f.call(a)); // this time we bind the function call to an object that has a name proerty, so the correct value is returned 

С другой стороны, путем создания анонимной функции вы вызываете ваш метод явно в области требуемого объекта ($ parent), поэтому этот связан правильно.

Надеюсь, это немного поможет ...:)

+0

AFAIK $ parent - это текущий элемент привязки foreach, поэтому я надеюсь, что он работает. Иногда мне интересно, какой смысл использовать протип при работе с этими проблемами. Можете ли вы указать на источник, объясняющий, как функция() {... дает правильный контекст? – FutuToad

+0

Да, как только я сел на свой велосипед, чтобы вернуться домой, я подумал, что так делаю! –

+0

Я не видел много явной документации по этой форме, применяемой к объектам, но ее можно в большинстве случаев использовать в документации по привязке кликов (http://knockoutjs.com/documentation/click-binding.html), где анонимная функция используется с функцией. – Grim

0

У вас есть $ parent в вашей привязке данных, поэтому он должен вызывать метод для родителя. Вы хотели иметь $ data.methodThatNeedsAccesToTheParentViewModel как привязку данных? Если вы это сделали, вам нужно изучить какую-либо структуру pubsub, либо knockout postbox, либо jquery pubsub plugin

+0

, потому что метод является прототипом, тогда «это» значение не является моделью экземпляров (normaly = $ parent в не прототипных методах), а скорее дочерним в каждом для каждого, что я не хочу , – FutuToad

8

У меня была такая же проблема, и я решил его таким образом:

<button data-bind="click: $parent.methodThatNeedsAccesToTheParentViewModel.bind($parent)">Edit</button> 
+0

Я также предпочитаю этот синтаксис, мне не нравится видеть 'function() {...}' материал в моих представлениях. –

Смежные вопросы