angularjsangularjs-directiveangularjs-bootstrap

Angular Directive function call on ng-change


I have an angular-bootstrap modal popup box that contains a custom directive in the template:

Modal.html

<div class="modal-header">
    <h3 class="modal-title">Modal Header</h3>
</div>
<div class="modal-body">
    <div class="row">
        <div class="col-md-12">
            <my-directive ng-model="test" ng-change="doSomething()" />
        </div>
    </div>
</div>
<div class="modal-footer">
    <button class="btn btn-primary" ng-click="upload()">Upload</button>
    <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>

ModalCtrl.js

app.controller('ModalCtrl', function ModalCtrl( $scope, $modalInstance ) {
    $scope.test = 'empty';

    $scope.upload = function() {
        $scope.test = 'change!';
    };

    $scope.cancel = function() {
        $modalInstance.dismiss('cancel');
    };
});

I open the modal popup from my main controller like this:

MainCtrl.js

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

app.controller('MainCtrl', function MainCtrl( $scope, $modal ) {
    $scope.openModal = function() {
        var modalInstance = $modal.open({
            templateUrl: '/assets/modals/Modal.html',
            controller: 'ModalCtrl',
            size: 'md'
        });
    };
});

As you can see from the above code, the modal template contains my custom directive <my-directive> which takes $scope.test - defined in the ModalCtrl - as it's model and should call $scope.doSomething() when that model changes.

The custom directive looks like this:

MyDirective.js

angular.module( 'myApp' ).directive( 'myDirective', function() {
    return {
        controller: function( $scope ) {
            $scope.doSomething = function() {
                console.log( 'doSomething() called! $scope.test now = ' + $scope.test );
            };
        },

        link: function( $scope, el, att ) {
            console.log( '$scope.test = ' + $scope.test );
        },

        template: '<div class="thumbnail"></div>'
    };
} );

When the modal popup opens the console prints out $scope.test = empty which is exactly what I expect to see. But when $scope.test is changed by calling the $scope.upload() function in ModalCtrl nothing happens! What I think should happen is $scope.doSomething() is called which then should print out in the console doSomething() called! $scope.test now = change!.

Any help would be much appreciated, this is driving me mad!


Solution

  • I figured it out. Instead of using ng-model and ng-change I added:

    scope: {
        test: '@'
    }
    

    to my directive and added this into my link function:

    $scope.$watch( 'test', function() { 
        console.log( 'test changed' ); 
    } );
    

    Then I add test as a parameter in my directives tag like so:

    <my-directive test="test" />
    

    and finally whenever I change $scope.test I call $scope.$apply() and voila!