AngularJS - Любой способ вызвать javascript после связывания шаблона?

Я пытаюсь использовать плагин jQuery (Plupload) с AngularJS. Я создал директиву, которая будет моим "виджетом" загрузки файла. Директива выглядит следующим образом (Код в функции ссылки является очень упрощенной версией примера на сайте Plupload):

.directive('myFileUpload', function () {
    return {
        restrict: 'E',
        replace: true,
        link: function(scope, element, attrs) {
            scope.uploaderProperties = {
                    runtimes : 'html5,flash,html4',
                    url : 'media/upload',
                    max_file_size : '10mb',
                    container: 'fileUploadContainer',
                    drop_element: 'fileUploadDropArea'
            };

            scope.uploader = new plupload.Uploader(scope.uploaderProperties);

            scope.uploader.init();

            scope.uploader.bind('FilesAdded', function(up, files) {
                scope.$apply();
            });
        },
        templateUrl: 'upload.html'
    };
});

Мой файл upload.html выглядит так:

<div id="{{uploaderProperties.container}}">
    <div id="{{uploaderProperties.drop_element}}" style="border: 1px black dashed;">Drop files here<br><br><br></div>
    Files to upload:<br>
    <div ng-repeat="currFile in uploader.files">{{currFile.name}} ({{currFile.size}}) </div>
    <br><br>
    <!-- for debugging -->
    {{uploader.files}}
    <br><br>
</div>

Когда я включаю директиву на свою страницу с элементом <my-file-upload>, все привязки данных происходят правильно. Проблема в том, что при запуске scope.uploader.init(); идентификаторы еще не были вставлены в DOM, поэтому Plupload жалуется и ломается, поскольку не может выбрать эти элементы. Если я просто жестко запрограммирую идентификаторы fileUploadContainer и fileUploadDropArea в шаблоне, он будет работать нормально. Однако мне бы очень хотелось определить эти идентификаторы только в одном месте.

Итак, есть ли способ запустить init() в загрузчике после того, как шаблон будет связан? Я думал об использовании $timeout для задержки запуска, но мне это показалось довольно серьезным приемом. Есть ли более правильный способ сделать это?

ОБНОВЛЕНИЕ

Я завернул init() в $timeout вот так

$timeout(function() {
    scope.uploader.init();
}, 2000);

просто чтобы убедиться, что он будет вести себя так, как я думал, и, конечно же, с этой задержкой плагин правильно настроен и работает. Однако я не хочу полагаться на время $timeout. Если бы я мог каким-то образом вызвать scope.uploader.init(); после связывания шаблона, все должно было работать нормально. Кто-нибудь знает хороший способ сделать это?


person dnc253    schedule 12.07.2012    source источник


Ответы (1)


На самом деле ваша проблема в другом - функция ссылки выполняется после вставки шаблона. Таким образом, в этом случае scope.uploaderProperties не устанавливается, когда выполняется шаблон.

Похоже, ваш шаблон слишком наворочен для опции templateUrl, правда. Вы можете попробовать вручную установить свои идентификаторы с помощью jQuery или настроить все в функции компиляции.

http://docs.angularjs.org/guide/directive

person Andrew Joslin    schedule 12.07.2012
comment
Я читал этот документ последние несколько дней и все еще пытаюсь полностью понять некоторые концепции. Вы говорите, что scope.uploaderProperties не задается, когда возникает шаблон, но когда я проверяю DOM, эти 2 div имеют правильные идентификаторы, полученные из uploaderProperties. Я неправильно понимаю, о чем вы говорите? Кроме того, с помощью функции компиляции, могу ли я просто настроить все свойства в функции pre, а затем просто выполнить инициализацию в функции post? Я до сих пор не совсем понимаю, что мне следует и не следует делать в частях функции компиляции. Спасибо за вашу помощь! - person dnc253; 12.07.2012
comment
Ну, идентификаторы будут установлены на следующей итерации после того, как сработает функция ссылки hte. Когда шаблон фактически вставлен, в scope.uploaderProperties ничего нет. Затем вы устанавливаете его, и функция ссылки находит его позже. И да, идея до и после публикации звучит как ваш лучший выбор. - person Andrew Joslin; 12.07.2012
comment
Я попробовал метод компиляции, но проблема все еще та же. Разве проблема не в том, что я описал в своем исходном посте? Plupload использует значения в свойствах контейнера и drop_element, чтобы выбрать эти элементы и настроить их для плагина. Когда метод init () запускается в функции связывания, {{}} еще не заменен для идентификаторов, поэтому он не может их выбрать. Я использовал $ timeout, чтобы отложить вызов init (), и тогда все работает нормально. Я просто не хочу полагаться на тайм-аут $ timeout. - person dnc253; 13.07.2012
comment
Если вы установите идентификаторы в предварительной ссылке или скомпилируете (вручную, создав элементы с помощью jquery или что-то еще), а затем вызовите init в пост-ссылке, он должен работать. - person Andrew Joslin; 14.07.2012
comment
Да, я вижу, что это работает. Это просто не так чисто, как хотелось бы. Я понимаю, что использование плагинов jQuery с Angular не всегда приводит к идеальному и чистому решению. Было бы неплохо, если бы для такого рода вещей существовал пост-шаблонный перехватчик ссылок ... Спасибо за то, что помог мне лучше разобраться в этом материале. - person dnc253; 15.07.2012
comment
Вы также можете попробовать сделать scope. $ Apply () в pre-link после того, как вы установите свойства, и он может обновить шаблон до post-link. Атрибут 'шаблон' - это просто ярлык, чтобы сделать все это самостоятельно. - person Andrew Joslin; 15.07.2012
comment
Когда я попробовал scope. $ Apply () в функции pre, я получил ошибку: $ digest уже выполняется. Если не считать того, что я сам управляю DOM, как вы предложили, я не знаю, действительно ли есть что-то, чего я хочу. Я думаю, может быть, у меня будут идентификаторы как в upload.html, так и в uploaderProperties. Их придется поддерживать вдвое, но вряд ли они когда-либо изменятся. - person dnc253; 15.07.2012
comment
Поскольку я изначально разместил этот вопрос, я сделал кучу больше с Angular и узнал о нем гораздо больше, и теперь я полностью понимаю, что вы предложили. Я не уверен, что это того стоит в моем случае, но поскольку другого ответа на то, что я хочу, не было, я приму этот ответ. - person dnc253; 07.09.2012