Подія надсилання, коли AngularJS закінчив завантаження


114

Цікаво, що найкращий спосіб виявити закінчення завантаження / завантаження сторінки, коли всі директиви виконуються при компілюванні / посиланні.

Якась подія вже є? Чи слід перевантажувати функцію завантаження?

Відповіді:


204

Лише підказка: чому б не подивитися на те, як це робить директива ngCloak? Очевидно, що директива ngCloak вдається показати вміст після завантаження речей. Б'юсь об заклад, перегляд ngCloak призведе до точної відповіді ...

EDIT через 1 годину: Добре, я переглянув ngCloak, і він справді короткий. Це, очевидно, означає, що функція компіляції не буде виконуватися, поки вирази {{template}} не будуть оцінені (тобто шаблон, який він завантажив), таким чином, приємна функціональність директиви ngCloak.

Моїм освіченим припущенням було б просто зробити директиву з тією ж простотою ngCloak, тоді у вашій функції компіляції робити все, що ви хочете зробити. :) Розмістіть директиву на кореневому елементі вашої програми. Ви можете назвати директиву на зразок myOnload і використовувати її як атрибут my-onload. Функція компіляції буде виконуватися після того, як шаблон буде скомпільований (вирази оцінені та завантажені під шаблони).

EDIT, 23 години потому: Гаразд, я зробив кілька досліджень, і я також задав власне питання . Питання, яке я задав, було опосередковано пов’язане з цим питанням, але воно випадково призводить мене до відповіді, яка вирішує це питання.

Відповідь полягає в тому, що ви можете створити просту директиву і помістити свій код у функцію посилання директиви, яка (у більшості випадків використання, пояснена нижче) буде запускатися, коли ваш елемент буде готовий / завантажений. Спираючись на опис Джоша про порядок виконання функцій компіляції та посилання ,

якщо у вас є така розмітка:

<div directive1>
  <div directive2>
    <!-- ... -->
  </div>
</div>

Тоді AngularJS створить директиви, виконуючи функції директив у певному порядку:

directive1: compile
  directive2: compile
directive1: controller
directive1: pre-link
  directive2: controller
  directive2: pre-link
  directive2: post-link
directive1: post-link

За замовчуванням пряма функція "link" - це постійна посилання, тому функція посилання на зовнішню директиву1 не буде працювати, поки не запущена функція внутрішнього зв'язку. Ось чому ми говоримо, що маніпуляцію з DOM безпечно лише в пост-посиланні. Отже, до оригінального питання не повинно виникнути проблем із доступом до внутрішнього html-директиви директиви через функцію зв'язку зовнішньої директиви, хоча динамічно вставлений вміст повинен бути складений, як було сказано вище.

З цього можна зробити висновок, що ми можемо просто скласти директиву для виконання нашого коду, коли все готово / складено / пов'язано / завантажено:

    app.directive('ngElementReady', [function() {
        return {
            priority: -1000, // a low number so this directive loads after all other directives have loaded. 
            restrict: "A", // attribute only
            link: function($scope, $element, $attributes) {
                console.log(" -- Element ready!");
                // do what you want here.
            }
        };
    }]);

Тепер ви можете поставити директиву ngElementReady на кореневий елемент програми, і вона console.logбуде запущена, коли вона завантажена:

<body data-ng-app="MyApp" data-ng-element-ready="">
   ...
   ...
</body>

Це так просто! Просто складіть просту директиву і використовуйте її. ;)

Ви можете додатково налаштувати його, щоб він міг виконувати вираз (тобто функцію), додавши $scope.$eval($attributes.ngElementReady);до нього:

    app.directive('ngElementReady', [function() {
        return {
            priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
            restrict: "A",
            link: function($scope, $element, $attributes) {
                $scope.$eval($attributes.ngElementReady); // execute the expression in the attribute.
            }
        };
    }]);

Тоді ви можете використовувати його на будь-якому елементі:

<body data-ng-app="MyApp" data-ng-controller="BodyCtrl" data-ng-element-ready="bodyIsReady()">
    ...
    <div data-ng-element-ready="divIsReady()">...<div>
</body>

Просто переконайтеся, що ваші функції (наприклад bodyIsReady та divIsReady) визначені в області (у контролері), під якою знаходиться ваш елемент.

Застереження: Я сказав, що це спрацює для більшості випадків. Будьте обережні, використовуючи певні директиви, такі як ngRepeat і ngIf. Вони створюють власну сферу дії, і ваша директива може не спрацьовувати. Наприклад, якщо ви покладете нову директиву ngElementReady на елемент, який також має ngIf, а умова ngIf оцінюється як false, то наша директива ngElementReady не завантажується. Або, наприклад, якщо ви покладете нову директиву ngElementReady на елемент, який також має директиву ngInclude, наша директива не буде завантажена, якщо шаблон для ngInclude не існує. Ви можете обійти деякі з цих проблем, переконавшись, що ви вкладаєте директиви, а не ставити їх на один і той же елемент. Наприклад, роблячи це:

<div data-ng-element-ready="divIsReady()">
    <div data-ng-include="non-existent-template.html"></div>
<div>

замість цього:

<div data-ng-element-ready="divIsReady()" data-ng-include="non-existent-template.html"></div>

Директива ngElementReady буде скомпільована в останньому прикладі, але функція зв'язку не буде виконуватися. Примітка: директиви завжди компілюються, але їх функції зв’язку не завжди виконуються залежно від певних сценаріїв, як описано вище.

Через кілька хвилин редагуйте:

О, і щоб повністю відповісти на питання, ви можете зараз $emitабо $broadcastвашу подію з виразу чи функції, виконаної в ng-element-readyатрибуті. :) Наприклад:

<div data-ng-element-ready="$emit('someEvent')">
    ...
<div>

EDIT, ще кілька хвилин пізніше:

@ відповідь satchmorun також працює, але лише для початкового навантаження. Ось дуже корисне запитання про те, що описує порядок виконання завдань, включаючи функції зв’язку app.runта ін. Отже, залежно від випадку використання, це app.runможе бути добре, але не для конкретних елементів, у цьому випадку функції зв’язку кращі.

EDIT, через п’ять місяців, 17 жовтня о 8:11 PST:

Це не працює з частками, які завантажуються асинхронно. Вам потрібно буде додати бухгалтерський облік у свої партії (наприклад, один із способів - зробити кожен частковий відстеження того, коли його вміст виконано завантаженням, то випромініть подію, щоб батьківський обсяг міг підрахувати кількість завантажених партій і, нарешті, зробити те, що потрібно робити після завантаження всіх партій).

EDIT, 23 жовтня о 22:52 PST:

Я створив просту директиву для запуску деякого коду при завантаженні зображення:

/*
 * This img directive makes it so that if you put a loaded="" attribute on any
 * img element in your app, the expression of that attribute will be evaluated
 * after the images has finished loading. Use this to, for example, remove
 * loading animations after images have finished loading.
 */
  app.directive('img', function() {
    return {
      restrict: 'E',
      link: function($scope, $element, $attributes) {
        $element.bind('load', function() {
          if ($attributes.loaded) {
            $scope.$eval($attributes.loaded);
          }
        });
      }
    };
  });

EDIT, 24 жовтня о 12:48 за PST:

Я вдосконалив свою первісну ngElementReadyдирективу та перейменував її на whenReady.

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. done loading all sub directives and DOM
 * content except for things that load asynchronously like partials and images).
 *
 * Execute multiple expressions by delimiting them with a semi-colon. If there
 * is more than one expression, and the last expression evaluates to true, then
 * all expressions prior will be evaluated after all text nodes in the element
 * have been interpolated (i.e. {{placeholders}} replaced with actual values). 
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length == 0) { return; }

      if (expressions.length > 1) {
        if ($scope.$eval(expressions.pop())) {
          waitForInterpolation = true;
        }
      }

      if (waitForInterpolation) {
        requestAnimationFrame(function checkIfInterpolated() {
          if ($element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            requestAnimationFrame(checkIfInterpolated);
          }
          else {
            evalExpressions(expressions);
          }
        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  }
}]);

Наприклад, використовуйте його так, щоб стріляти, someFunctionколи елемент завантажений і {{placeholders}}ще не замінений:

<div when-ready="someFunction()">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunctionбуде викликано до item.propertyзаміни всіх заповнювачів.

Оцініть стільки виразів, скільки ви хочете, і зробіть останній вираз, trueщоб чекати, {{placeholders}}щоб його оцінили так:

<div when-ready="someFunction(); anotherFunction(); true">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunctionі anotherFunctionбуде звільнено після {{placeholders}}заміни.

Це працює лише під час першого завантаження елемента, а не на майбутні зміни. Це може не працювати за бажанням, якщо $digestтриває ситуація після того, як спочатку замінено заповнювачі (дайджест $ може статися до 10 разів, поки дані не перестануть змінюватися). Він підходить для переважної більшості випадків використання.

EDIT, 31 жовтня о 19:26 PST:

Гаразд, це, мабуть, моє останнє та остаточне оновлення. Це, ймовірно, спрацює для 99,999 випадків використання там:

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. when it's done loading all sub directives and DOM
 * content). See: /programming/14968690/sending-event-when-angular-js-finished-loading
 *
 * Execute multiple expressions in the when-ready attribute by delimiting them
 * with a semi-colon. when-ready="doThis(); doThat()"
 *
 * Optional: If the value of a wait-for-interpolation attribute on the
 * element evaluates to true, then the expressions in when-ready will be
 * evaluated after all text nodes in the element have been interpolated (i.e.
 * {{placeholders}} have been replaced with actual values).
 *
 * Optional: Use a ready-check attribute to write an expression that
 * specifies what condition is true at any given moment in time when the
 * element is ready. The expression will be evaluated repeatedly until the
 * condition is finally true. The expression is executed with
 * requestAnimationFrame so that it fires at a moment when it is least likely
 * to block rendering of the page.
 *
 * If wait-for-interpolation and ready-check are both supplied, then the
 * when-ready expressions will fire after interpolation is done *and* after
 * the ready-check condition evaluates to true.
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;
      var hasReadyCheckExpression = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length === 0) { return; }

    if ($attributes.waitForInterpolation && $scope.$eval($attributes.waitForInterpolation)) {
        waitForInterpolation = true;
    }

      if ($attributes.readyCheck) {
        hasReadyCheckExpression = true;
      }

      if (waitForInterpolation || hasReadyCheckExpression) {
        requestAnimationFrame(function checkIfReady() {
          var isInterpolated = false;
          var isReadyCheckTrue = false;

          if (waitForInterpolation && $element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            isInterpolated = false;
          }
          else {
            isInterpolated = true;
          }

          if (hasReadyCheckExpression && !$scope.$eval($attributes.readyCheck)) { // if the ready check expression returns false
            isReadyCheckTrue = false;
          }
          else {
            isReadyCheckTrue = true;
          }

          if (isInterpolated && isReadyCheckTrue) { evalExpressions(expressions); }
          else { requestAnimationFrame(checkIfReady); }

        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  };
}]);

Використовуйте його так

<div when-ready="isReady()" ready-check="checkIfReady()" wait-for-interpolation="true">
   isReady will fire when this {{placeholder}} has been evaluated
   and when checkIfReady finally returns true. checkIfReady might
   contain code like `$('.some-element').length`.
</div>

Звичайно, це може бути оптимізовано, але я просто залишу це на цьому. requestAnimationFrame приємно.


3
Дійсно дратує всі ті префікси "дані". Я радий, що сам їх не використовую.
stolsvik

1
@stolsvik Гей, так, у сучасних браузерах вони не потрібні.
trusktr

49
Заслуговує на голосування за кількість часу та зусиль, вкладених у цю відповідь. Хороша робота!
GordyD

8
Приємна відповідь, але, будь ласка, подумайте про те, щоб видалити всі рядки "Редагувати" та трохи змінити відповідь. Історія редагування доступна через посилання "відредаговано ..." внизу вашої відповіді, і це відволікається під час читання.
user247702

2
Вихідний код був би справді корисним. І якщо ви можете оприлюднити це в npm, це було б досконало. Дійсно приємна відповідь, дуже добре пояснена, +1 за велику кількість зусиль, докладених до цього.
tfrascaroli

38

У документах для документа міститьсяangular.Module запис, що описує runфункцію:

Використовуйте цей метод для реєстрації роботи, яку слід виконувати, коли інжектор виконує завантаження всіх модулів.

Тож якщо у вас є модуль, який є вашим додатком:

var app = angular.module('app', [/* module dependencies */]);

Ви можете запускати матеріали після завантаження модулів:

app.run(function() {
  // Do post-load initialization stuff here
});

EDIT: Ручна ініціалізація на допомогу

Тож було зазначено, що runне можна телефонувати, коли DOM буде готовий та пов'язаний. Він викликається, коли $injectorмодуль, на який посилається, ng-appзавантажив усі його залежності, що є окремим від кроку компіляції DOM.

Я ще раз подивився на ручну ініціалізацію , і, здається, це повинно зробити трюк.

Я склав загадку для ілюстрації .

HTML простий:

<html>
    <body>
        <test-directive>This is a test</test-directive>
    </body>
</html>

Зверніть увагу на відсутність ng-app. І в мене є директива, яка дозволить зробити деякі маніпуляції з DOM, щоб ми могли переконатися в порядку та термінах речей.

Як завжди, модуль створюється:

var app = angular.module('app', []);

І ось директива:

app.directive('testDirective', function() {
    return {
        restrict: 'E',
        template: '<div class="test-directive"><h1><div ng-transclude></div></h1></div>',
        replace: true,
        transclude: true,
        compile: function() {
            console.log("Compiling test-directive");
            return {
                pre: function() { console.log("Prelink"); },
                post: function() { console.log("Postlink"); }
            };
        }
    };
});

Ми будемо замінювати test-directiveтег divкласом test-directiveі загортати його вміст у h1.

Я додав функцію компіляції, яка повертає функції до і після посилання, щоб ми могли бачити, коли ці речі виконуються.

Ось решта коду:

// The bootstrapping process

var body = document.getElementsByTagName('body')[0];

// Check that our directive hasn't been compiled

function howmany(classname) {
    return document.getElementsByClassName(classname).length;
}

Перш ніж ми щось зробили, test-directiveу DOM не повинно бути елементів із класом , а після того, як ми зробимо, це повинно бути 1.

console.log('before (should be 0):', howmany('test-directive'));

angular.element(document).ready(function() {
    // Bootstrap the body, which loades the specified modules
    // and compiled the DOM.
    angular.bootstrap(body, ['app']);

    // Our app is loaded and the DOM is compiled
    console.log('after (should be 1):', howmany('test-directive'));
});

Це досить просто. Коли документ буде готовий, телефонуйте angular.bootstrapз кореневим елементом вашої програми та масивом імен модулів.

Насправді, якщо ви приєднаєте runфункцію до appмодуля , ви побачите, що він запускається до того, як відбудеться будь-яке компілювання.

Якщо ви запустите скрипку і переглянете консоль, ви побачите наступне:

before (should be 0): 0 
Compiling test-directive 
Prelink
Postlink
after (should be 1): 1 <--- success!

2
дякую @satchmorun! але run () виконує до кінця посилальної частини - просто перевірив це деякими console.logs.
Lior

мені було цікаво ... У мене є директива, яка спрацьовує, щоб реалізувати деякі плагіни jQuery DOM, runспрацьовує перед директивою, а при запуску пожеж html ще не все
charlietfl

@charlietfl - я трохи розробив ручне завантаження, і це насправді досить простий спосіб отримати те, що питання шукає. Я додав досить тривалу редагування до своєї оригінальної відповіді.
satchmorun

5
Я виявив, що, використовуючи $timeout( initMyPlugins,0)роботи в рамках моєї директиви, все те, що мені потрібно, там
charlietfl,

@satchmorun, дивіться наступні дії: stackoverflow.com/questions/14989161/…
Lior

16

Angular не надав спосіб сигналізувати про завершення завантаження сторінки, можливо тому, що "готовий" залежить від вашої програми . Наприклад, якщо у вас є ієрархічне дерево партій, один завантажує інші. "Готово" означало б, що всі вони завантажені. Будь-який фреймворк буде важко проаналізувати ваш код і зрозуміти, що все зроблено або все ще чекають. Для цього вам доведеться надати логіку для додатків, щоб перевірити та визначити це.


14

Я придумав рішення, яке є досить точним при оцінці завершення кутової ініціалізації.

Директива така:

.directive('initialisation',['$rootScope',function($rootScope) {
            return {
                restrict: 'A',
                link: function($scope) {
                    var to;
                    var listener = $scope.$watch(function() {
                        clearTimeout(to);
                        to = setTimeout(function () {
                            console.log('initialised');
                            listener();
                            $rootScope.$broadcast('initialised');
                        }, 50);
                    });
                }
            };
        }]);

Потім їх можна просто додати як атрибут до bodyелемента і потім прослухати для використання$scope.$on('initialised', fn)

Це працює, якщо припустити, що програма ініціалізується, коли немає більше циклів переваривання $. $ watch називається кожним циклом дайджесту, і тому запускається таймер (setTimeout не $ timeout, тому новий цикл дайведу не запускається). Якщо цикл дайджесту не відбудеться протягом тайм-ауту, тоді програма вважається ініціалізованою.

Це, очевидно, не настільки точне, як рішення satchmoruns (можливо, що цикл перетравлення займає більше часу, ніж час очікування), але моє рішення не потребує того, щоб ви стежили за модулями, що робить його набагато простіше в управлінні (особливо для великих проектів ). У будь-якому випадку, здається, досить точним для моїх вимог. Сподіваюся, це допомагає.


Відмінне рішення. Для проектів, коли весь код в одному або двох стислих файлах працює дуже добре.
merqlove

1
Це фантастичне рішення. Якщо у вас є багато коду в jquery, і ви намагаєтеся перетворити код у кутовий крок за кроком, це має ідеальний сенс.
Mangesh Pimpalkar

11

Якщо ви використовуєте Angular UI Router , ви можете прослухати $viewContentLoadedподію.

"$ viewContentLoaded - запускається, коли огляд завантажується, після надання DOM . Поле" $ "перегляду видає подію." - Посилання

$scope.$on('$viewContentLoaded', 
function(event){ ... });

3
$ range. $ watch ('$ viewContentLoaded', function () зробив для мене хитрість
Людовик XIV

2
прихильне до того, "яким ти повинен бути". Що робити, якщо я сказав "якщо ви використовуєте React замість Angular (яким ви повинні бути) ..."? Не дуже ставлення до цієї екосистеми ІМХО.
Valentin Waeselynck

@ValentinWaeselynck Ви абсолютно праві. Я відредагував свою відповідь, щоб усунути свою упередженість.
Йордан Сколе

1
Працювали для мене! Дякую. Я фактично додав його до своєї функції запуску, потім змінив $ range на $ rootScope.
JDavies

2
Як зазначає Angular University в іншій відповіді, $ viewContentLoaded, можливо, не існував спочатку, але зараз він працює у вбудованого постачальника ngRoute точно так само. Зважаючи на це, я думаю, що це швидка, проста, читабельна відповідь, яку шукають багато (більшість?) Майбутніх читачів.
Кевін Крамлі

3

я спостерігаю, як DOM маніпулює кутовим з JQuery, і я встановив фініш для свого додатка (якась заздалегідь визначена та задовільна ситуація, яка мені потрібна для мого реферату додатка), наприклад, я очікую, що мій нг-ретранслятор дасть 7 результат, і там я встановить для цього функцію спостереження за допомогою setInterval.

$(document).ready(function(){

  var interval = setInterval(function(){

  if($("article").size() == 7){
     myFunction();
     clearInterval(interval);
  }

  },50);

});

3
Я б цього не робив. Використання інтервалів для перевірки того, що відбувається, не є хорошою практикою, незмінна, і є й інші способи зробити так, щоб це сталося. Таймери призначені для виконання конкретних завдань, які повинні відбутися через певний проміжок часу, а не для «здогадки», коли вміст або результати готові.
dudewad

Не кажучи вже про те, що використання таймера jquery проти кутової платформи є контрпродуктивним - кутовий має клас таймауту, і вам слід скористатись тим, що в іншому випадку ви обминаєте дві рамки, і це дуже швидко плутається.
dudewad

3

Якщо ви не використовуєте модуль ngRoute , тобто у вас немає події $ viewContentLoaded .

Можна використовувати інший метод директиви:

    angular.module('someModule')
        .directive('someDirective', someDirective);

    someDirective.$inject = ['$rootScope', '$timeout']; //Inject services

    function someDirective($rootScope, $timeout){
        return {
            restrict: "A",
            priority: Number.MIN_SAFE_INTEGER, //Lowest priority
            link    : function(scope, element, attr){
                $timeout(
                    function(){
                        $rootScope.$emit("Some:event");
                    }
                );
            }
        };
    }

Відповідно до відповіді trusktr, вона має найнижчий пріоритет. Плюс $ timeout змусить Angular пробігати через весь цикл подій перед виконанням зворотного дзвінка.

$ rootScope використовується, оскільки він дозволяє розміщувати директиви в будь-якій області програми та повідомляти лише необхідних слухачів.

$ rootScope. $ emit почне подія для всіх $ rootScope. $ лише для слухачів. Цікава частина полягає в тому, що $ rootScope. $ Мовлення сповістить про всі $ rootScope. $ На, а також про $ range. $ Для слухачів Джерело


2

За даними команди Angular і цього випуску Github :

тепер у нас є $ viewContentLoaded і $ includeContentLoaded події, які випромінюються в ng-view та ng-include відповідно. Я думаю, що це так близько, як можна зрозуміти, коли ми закінчимо компіляцію.

Виходячи з цього, здається, це наразі неможливо зробити надійним способом, інакше Angular забезпечив би подію поза коробкою.

Завантаження програми передбачає запуск циклу дайджесту в кореневій області, а також не завершено подію циклу дайджесту.

Згідно з документами проектування Angular 2 :

Через множинні дайджести неможливо визначити та повідомити компонент про стабільність моделі. Це відбувається тому, що повідомлення може додатково змінити дані, що може відновити процес прив’язки.

Згідно з цим, той факт, що це неможливо, є однією з причин, чому було прийнято рішення про перезапис у Angular 2.


2

У мене був фрагмент, який завантажувався після / основною частиною, що надходила за допомогою маршрутизації.

Мені потрібно було запустити функцію після того, як завантажився цей підрозділ, і я не хотів писати нову директиву, і я зрозумів, що ти можеш використовувати зухвало ngIf

Контролер батьківського часткового:

$scope.subIsLoaded = function() { /*do stuff*/; return true; };

HTML підроздільний

<element ng-if="subIsLoaded()"><!-- more html --></element>

1

Якщо ви хочете генерувати JS за допомогою серверних даних (JSP, PHP), ви можете додати свою логіку до сервісу, який буде завантажений автоматично при завантаженні контролера.

Крім того, якщо ви хочете реагувати, коли всі директиви виконуються за компіляцією / зв'язуванням, ви можете додати відповідні запропоновані рішення вище в логіці ініціалізації.

module.factory('YourControllerInitService', function() {

    // add your initialization logic here

    // return empty service, because it will not be used
    return {};
});


module.controller('YourController', function (YourControllerInitService) {
});

0

Це все чудові рішення, однак, якщо ви зараз використовуєте маршрутизацію, то я вважав, що це рішення є найпростішим та найменшим необхідним кодом. Використання властивості "вирішити", щоб дочекатися завершення обіцянки перед запуском маршруту. напр

$routeProvider
.when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        message: function(messageService){
            return messageService.getMessage();
    }
}

})

Клацніть тут, щоб отримати повний документ - Кредит К. Скотта Аллена


0

можливо, я можу допомогти вам на цьому прикладі

У користувальницькій фан-боксі я показую вміст з інтерпольованими значеннями.

в сервісі, в методі "відкритого" fancybox, я роблю

open: function(html, $compile) {
        var el = angular.element(html);
     var compiledEl = $compile(el);
        $.fancybox.open(el); 
      }

$ compile повертає зібрані дані. ви можете перевірити складені дані

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.