В шаблонах в Ember.js, как вы относитесь к значению в родительском контексте, когда находитесь внутри блока #each?
У меня есть ситуация в шаблоне, где я хочу использовать блок if в значении в родительском контексте, находясь внутри каждого блока.
Код:
App = Ember.Application.create({});
App.view = Ember.View.extend({
foo: [1, 2, 3],
bar: true
});
Шаблон:
<script type="text/x-handlebars">
{{#view App.view}}
{{#each foo}}
{{#if bar}}
{{this}}
{{/if}}
{{/each}}
{{/view}}
</script>
Это не работает, потому что имена, указанные внутри каждого цикла, привязаны к элементу итерации. Как вы относитесь к вещам в родительском контексте?
Демо: http://jsfiddle.net/hekevintran/sMeyC/1/
Ответы
Ответ 1
Я нашел лучшее решение.
Из руководства Embed.js View Layer (http://emberjs.com/guides/understanding-ember/the-view-layer/):
Помощники ручек в Ember могут также указывать переменные. Например, в форме {{#with controller.person as tom}} задается переменная tom, к которой могут обращаться потоки потомков. Даже если дочерний контекст имеет свойство tom, переменная tom заменит его.
Эта форма имеет одно важное преимущество: она позволяет сократить длинные пути, не теряя доступ к родительской области.
Это особенно важно в помощнике {{#each}}, который предоставляет форму {{#each person in people}}. В этой форме контекст потомков имеет доступ к переменной человека, но остается в той же области, где шаблон вызывается каждый.
Шаблон:
<script type="text/x-handlebars" >
{{#view App.view}}
{{#each number in view.foo}}
{{#if view.bar}}
{{number}}
{{/if}}
{{/each}}
{{/view}}
</script>
Демо: http://jsfiddle.net/hekevintran/hpcJv/1/
Ответ 2
Какой ответ hekevintran означает, что вы можете переименовать любую переменную с помощью #with
. У нас аналогичная проблема с JavaScript с this
. В JavaScript иногда вы увидите такой код, чтобы обойти его.
var self = this;
doSomething(function() {
// Here, `this` has changed.
if (self.bar) {
console.log(this);
}
});
В рулевых ручках, украшенных Ember, что-то подобное происходит с view
. Скажем, у вас есть App.MyOuterView и еще один вид внутри него. Вы можете обойти это так.
{{#with view as myOuterView}}
{{#each foo}}
{{#if myOuterView.bar}}
{{this}}
{{/if}}
{{/each}}
{{/with}}
Подобно JavaScript, вы можете по существу переименовать view
в другое, чтобы он не затенял внутренний вид. {{#each person in people}}
является лишь частным случаем этого. Но переименование с помощью {{#with view as myView}}
является более общим решением/обходным решением этой проблемы, которое также работает с вложенными вызовами помощника view
.
Ответ 3
Я тоже был в тупике. Этот поток и этот другой поток (Использование представления контейнера в ember.js - как получить доступ к родительским переменным из дочернего представления) помогли мне с решением. Я использовал предложение Джонатана сделать {#with}, а также выяснил, что я должен получить доступ к моей переменной, вызвав контроллер. Моя работала так:
// I use the #which command to preserve access to the outer context once inside the #each
{{#with view as myOuterView}}
{{#each myInnerArray}}
//here, i get my 'name' property from the *controller* of myOuterView
{{myOuterView.controller.name}}
// stuff i did in inner array
{{/each}
{{/with}
Ответ 4
Не нужно размещать if
внутри each
в первую очередь:
<script type="text/x-handlebars">
{{#view App.view}}
{{#if view.bar}}
{{#each view.foo}}
{{this}}
{{/each}}
{{/if}}
{{/view}}
</script>
Демо: http://jsfiddle.net/ppanagi/NQKvy/35/