Ember.js - Использование помощника Handlebars для определения того, что подпредставление отрисовало
Есть множество вопросов, которые так или иначе задают: «Как мне сделать что-то после того, как какая-то часть представления отрисована? "(Вот,Вот, а такжеВот просто чтобы дать несколько). Ответ обычно таков:
использованиеdidInsertElement
запустить код, когда представлениепервоначально оказаны.использованиеEmber.run.next(...)
запустить ваш кодпосле изменения представления сбрасываются, если вам нужен доступ к созданным элементам DOM.использовать наблюдателя наisLoaded
или подобное свойство, чтобы сделать что-то последанные вам нужно загружено.Какие'раздражает то, что это приводит к некоторым очень неуклюже выглядящим вещам как это:
didInsertElement: function(){
content.on('didLoad', function(){
Ember.run.next(function(){
// now finally do my stuff
});
});
}
И это нена самом деле даже не обязательно работать, когда тывы используете ember-data, потому чтоisLoaded
может уже иметь значение true (если запись уже была загружена ранее и больше не запрашивается с сервера). Так что получить правильную последовательность очень сложно.
Кроме того, выВы, вероятно, уже смотрите isLoaded в вашем шаблоне представления следующим образом:
{{#if content.isLoaded}}
{{else}}
Loading data...
{{/if}}
и делать это снова в вашем контроллере кажется дублированием.
Я придумал немного новое решение, но оно либо требует работы, либо на самом деле плохая идея ... любой случай может быть правдой:
Я написал небольшой помощник руль под названием{{fire}}
это вызовет событие с пользовательским именем, когда будет выполнен содержащий шаблон handlebars (то есть, это должно происходить каждый раз, когда подпредставление перерисовывается, верно?).
Вот мойочень ранняя попытка:
Ember.Handlebars.registerHelper('fire', function (evtName, options) {
if (typeof this[evtName] == 'function') {
var context = this;
Ember.run.next(function () {
context[evtName].apply(context, options);
});
}
});
который используется так:
{{#if content.isLoaded}}
{{fire typeaheadHostDidRender}}
{{else}}
Loading data...
{{/if}}
По сути, это работает как есть, но у него есть пара недостатков, о которых я уже знаю:
Он вызывает метод на контроллере ... было бы лучше, по крайней мере,в состоянии отправить "событие" вместо этого к объекту представления предка, возможно, даже для того, чтобы сделать это поведением по умолчанию. Я старался{{fire typeaheadHostDidRender target="view"}}
и это нет работа. Я могу'пока не вижу, как получить "ток" вид из того, что передается в помощник, но, очевидно,{{view}}
Помощник может сделать это.Я предполагаю, что есть более формальный способ вызвать пользовательское событие, чем то, что яя делаю здесь, но у меня нетя еще не научился этому. JQuery-х.trigger()
Безразлично»Кажется, что он работает на объектах контроллера, хотя он может работать на представлениях. Есть "Эмбер» способ сделать это?Там могут быть вещи, которые я нене понимаю, как в случае, когда это событие будет вызвано, но представление не былона самом деле будет добавлено в DOM ...?Как вы можете догадаться, яиспользуя Bootstrap 's Typeahead control, и мне нужно подключить его после рендеринга, что на самом деле происходит только после нескольких вложенных
{{#if}}
блоки оценивают как истинные в моем шаблоне. Я также использую jqPlot, поэтому я часто сталкиваюсь с необходимостью этого шаблона. Это кажется жизнеспособным и полезным инструментом, но это может быть яМне не хватает чего-то большого, что делает этот подход глупым. Или, может быть, тамЭто еще один способ сделать это, нене показывается в моих поисках?
Может ли кто-нибудь улучшить этот подход для меня или сказать, почемуплохая идея?
UPDATEI»мы выяснили несколько битов:
Я могу получить первыйреальный» содержащий представление сoptions.data.view.get('parentView')
... очевидно, но я неЯ думаю, это будет так просто.Вы действительно можете сделать JQuery-стильobj.trigger(evtName)
на любом произвольном объекте ... но объект должен расширятьEmber.Evented
подмешать! Так что я полагаю, что это правильный способ отправки событий такого рода в Ember. Просто убедитесь, что предполагаемая цель расширяетсяEmber.Evented
(взгляды уже делают).Вот'На данный момент улучшенная версия:
Ember.Handlebars.registerHelper('fire', function (evtName, options) {
var view = options.data.view;
if (view.get('parentView')) view = view.get('parentView');
var context = this;
var target = null;
if (typeof view[evtName] == 'function') {
target = view;
} else if (typeof context[evtName] == 'function') {
target = context;
} else if (view.get('controller') && typeof view.get('controller')[evtName] == 'function') {
target = view.get('controller');
}
if (target) {
Ember.run.next(function () {
target.trigger(evtName);
});
}
});
Теперь почти все, что ям отсутствует - выяснить, как пройти в предполагаемую цель (например, контроллер или представление - приведенный выше код пытается угадать). Или выяснить, есть лиНекоторое неожиданное поведение, которое нарушает всю концепцию.
Любой другой вклад?