AngularJS: $viewContentLoaded fired before partial view appears

旧街凉风 提交于 2019-11-27 13:09:35
T4deu

This is related to angular digest cycle, it's about how angular works underneath the hood, data binding etc. There are great tutorials explaining this.

To solve your problem, use $timeout, it will make the code execute on the next cycle, whem the ng-if was already parsed:

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

Fixed demo here: http://codepen.io/anon/pen/JoYPdv

But I strongly advise you to use directives do any DOM manipulation, the controller isn't for that. Here is a example of how do this: Easy dom manipulation in AngularJS - click a button, then set focus to an input element

I have solved this issue with the help of Directives. Add one direcitve to your element (like <div my-dir></div>) and do manipulations to the element in respective directive as follows,

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

I have also tried state provider events like $stateChangeSuccess, $viewContentLoaded but couldn't solve the issue. Because after those events got fired, it's taking time to render on the DOM.

So, we can follow this approach which gives perfect results and proper way to implement in Angular JS :)

This is an answer to Hades a bit late but might help someone else. I setup a service which I will later be able to call from a controller or directive.

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

    };
});

In the controller or directive include viewContentLoaded and call the get function with the promise. Don't forget to change the app to whatever you app name is and include the service file to be loaded.

viewContentLoaded.getLoaded().then(function(){
    //Remove Listner when done
    viewContentLoaded.removeViewContenListner();
    //Your code to run       

}, function(reason) {
    //$log.error(reason);
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!