Michael
Michael

Reputation: 2566

$document.ready and ng-model

I do have a directive from which i'm trying to apply a bootstrap collapse function once the document is ready.

To do so I have to browse each object of a collection.

My directive looks something like this :

'use strict';

angular.module('app').directive("adScheduleTimeline",function($document) {
    return {
        restrict: 'E',
        scope:{
            ngModel: '='
        },
        templateUrl: '/partials/schedule/ad-schedule-timeline',
        link: function (scope, el, attrs) {
            scope.panelBaseId = attrs.collapsePanelBodyId;
            scope.panelId = attrs.collapsePanelId;

            $document.ready(function(){
                console.log(scope.ngModel)
                angular.forEach(scope.ngModel, function(value, key){
                    if (value.collapsed)
                    {
                        $("#" + scope.panelBaseId + "-" + key).collapse('show');
                    }
                });
            });
        }
    };
});

Once I load the page, the scope.ngModelis undefined and therefore the collapse function is not working. Is there any better way to implement a similar function on page load.

For info, the collapse function is coming from Bootstrap2.x.x. i'm not using angular-ui-bootstrap.

Upvotes: 0

Views: 663

Answers (3)

runTarm
runTarm

Reputation: 11547

You could use scope.$watch() to wait until the value of scope.ngModel is populated.

link: function (scope, el, attrs) {
    scope.panelBaseId = attrs.collapsePanelBodyId;
    scope.panelId = attrs.collapsePanelId;

    scope.$watch('ngModel', function (model) {
        if (!model) { return; }

        angular.forEach(model, function(value, key) {
            if (value.collapsed) {
                $("#" + scope.panelBaseId + "-" + key).collapse('show');
            }
        });
    });
}

And if you would like to do it only once, i.e. no need to call collapse() again when the scope.ngModel has been changed later. You could unwatch it like this:

link: function (scope, el, attrs) {
    scope.panelBaseId = attrs.collapsePanelBodyId;
    scope.panelId = attrs.collapsePanelId;

    var unwatch = scope.$watch('ngModel', function (model) {
        if (!model) { return; }

        unwatch();

        angular.forEach(model, function(value, key) {
            if (value.collapsed) {
                $("#" + scope.panelBaseId + "-" + key).collapse('show');
            }
        });
    });
}

BTW, the $document.ready() is useless here, the angular will wait the document to be ready before start bootstraping anyway.

Hope this helps.

Upvotes: 3

Dennis Traub
Dennis Traub

Reputation: 51684

Try hooking into the $viewContentLoaded event:

link: function (scope, el, attrs) {
    ...

    scope.$on('$viewContentLoaded', function() {
        console.log(scope.ngModel);
        angular.forEach(scope.ngModel, function(value, key) {
            if (value.collapsed) {
                $("#" + scope.panelBaseId + "-" + key).collapse('show');
            }
        });
    };
}

Upvotes: 0

Endless
Endless

Reputation: 37915

Not tested...

'use strict';

angular.module('app').directive("adScheduleTimeline",function($document) {
    return {
        restrict: 'E',
        require: '?ngModel',
        templateUrl: '/partials/schedule/ad-schedule-timeline',
        link: function (scope, el, attrs, ctrl) {
            scope.panelBaseId = attrs.collapsePanelBodyId;
            scope.panelId = attrs.collapsePanelId;

            if(ctrl.$modelValue)
            {
                angular.forEach(ctrl.$modelValue, function(value, key){
                    if (value.collapsed)
                    {
                            $("#" + scope.panelBaseId + "-" + key).collapse('show');
                    }
                });
            }
        }
    };
})

Upvotes: 0

Related Questions