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);
        });
    }
});

Теперь почти все, что ям отсутствует - выяснить, как пройти в предполагаемую цель (например, контроллер или представление - приведенный выше код пытается угадать). Или выяснить, есть лиНекоторое неожиданное поведение, которое нарушает всю концепцию.

Любой другой вклад?

Ответы на вопрос(1)

Ваш ответ на вопрос