AngularJS: $ viewContentLoaded, выпущенный до частичного просмотра

Для частичного представления я хочу сделать некоторые вещи JavaScript, которые я обычно делал бы с $(document).ready(function() {...}) , например, связывать зрителей с элементами. Я знаю, что это не работает для AngularJS и частичных представлений, загруженных в представление «root».

Таким образом, я добавил слушателя к controllerу, который прослушивает событие $viewContentLoaded . Вызывается функция прослушивателя, поэтому событие запускается, но мне кажется, что это происходит до отображения частичного представления. Я также не вижу элементы, когда я устанавливаю точку останова в функции слушателя и отлаживаю ее с помощью firebug, а также выбор jquery внутри функции не находит элементы частичного представления.

Это выглядит так:

 angular.module('docinvoiceClientAngularjsApp') .controller('LoginController', function ($scope, $rootScope) { $scope.$on('$viewContentLoaded', function(event) { console.log("content loaded"); console.log($("#loginForm")); // breakpoint here }); [...] 

Я предполагаю, что я делаю что-то не так, поскольку должно быть больше сообщений о stackoverflow, если это обычная ошибка.

Поскольку я использую ui-router и ui-view , я дам вам отрывок файла маршрутизации:

 angular .module('docinvoiceClientAngularjsApp', [ 'ui.router', 'ngAnimate', 'ngCookies', 'ngResource', 'ngMessages', 'ngRoute', 'ngSanitize', 'ngTouch' ]) .config(function ($routeProvider, $stateProvider) { $stateProvider .state('login', { url: '/', templateUrl: 'components/login/loginView.html', controller: 'LoginController' }) .run(['$state', function ($state) { $state.transitionTo('login'); }]) [...] 

Любая помощь приветствуется. Спасибо и добрые пожелания

ОБНОВЛЕНИЕ 1: я удалил ошибку до следующей утилиты: loginView.html выглядит следующим образом:

 
[...]

Как только я удалю ng-if из тега div, он работает так, как ожидалось. Событие запускается после рендеринга DOM, поэтому jQuery находит элемент. Если ng-if привязан к тегу div, поведение описано так же, как описано выше.

ОБНОВЛЕНИЕ 2: Как и было обещано, я добавил рабочую демонстрацию, которая показывает различное поведение при добавлении директивы ng-if . Может ли кто-нибудь указать мне правильное направление? Не придерживайтесь формы входа в систему как таковой, поскольку есть много других случаев использования, когда я хочу удалить определенные части представления на основе некоторого выражения и сделать некоторые вещи JavaScript после частичного представления.

Вы можете найти рабочую демонстрацию здесь: Демо

Это связано с угловым циклом дайджеста, речь идет о том, как угловые работы под капотом, привязка данных и т. Д. Есть большие учебники, объясняющие это.

Чтобы решить вашу проблему, используйте $ timeout, это сделает код выполненным в следующем цикле, если ng-if уже был разобран:

 app.controller('LoginController', function ($scope, $timeout) { $scope.$on('$viewContentLoaded', function(event) { $timeout(function() { $scope.formData.value = document.getElementById("loginForm").id; },0); }); }); 

Исправлена ​​демо: http://codepen.io/anon/pen/JoYPdv

Но я настоятельно рекомендую вам использовать директивы для любых манипуляций с DOM, controller не для этого. Вот пример того, как это сделать: легкая манипуляция dom в AngularJS – нажмите кнопку, затем установите фокус на элемент ввода

Я решил эту проблему с помощью директив. Добавьте один директиву в свой элемент (например,

) и выполните манипуляции с элементом в соответствующей директиве следующим образом:

 app.directive('myDir', function () { return { restrict: 'A', link: function (scope, element) { // Do manipulations here with the help of element parameter } }; }); 

Я также пробовал события государственного провайдера, такие как $stateChangeSuccess , $viewContentLoaded но не смог решить проблему. Потому что после того, как эти события были уволены, требуется время для рендеринга в DOM.

Таким образом, мы можем следовать этому подходу, который дает отличные результаты и правильный способ реализации в Angular JS 🙂

Это ответ Аиду немного поздно, но может помочь кому-то другому. Я настраиваю службу, которую позже позвоню с controllerа или директивы.

 'use strict'; app.factory('viewContentLoaded', function($q, $rootScope, $timeout) { var viewContentLoaded = $q.defer(), foo = function() { $timeout(function() { viewContentLoaded.resolve(); // Get all entries }, 100);//Timeout }, checkViewContenLoadedListner = $rootScope.$on('$viewContentLoaded', foo);//Rootscope return { getLoaded: function() { return viewContentLoaded.promise; }, removeViewContenListner: function() { //Remove event listern on $viewContentLoaded no $off so call it will unsubscribe it //$rootScope.$off('$viewContentLoaded', foo);//Rootscope //Don't forget to unsubscribe later checkViewContenLoadedListner(); } }; }); 
Interesting Posts
Давайте будем гением компьютера.