daydreamer
daydreamer

Reputation: 91959

scope change doesn't execute code in directive

Here is what my directive looks like

//noinspection JSCheckFunctionSignatures
angular.module('notificationDirective', []).directive('notification', function ($timeout) {
    //noinspection JSUnusedLocalSymbols
    return {
        restrict: 'E',
        replace: true,
        scope: {
            ngModel: '@'
        },
        template: '<div class="alert fade" bs-alert="ngModel"></div>',
        link: function (scope, element, attrs) {
            scope.$watch('message', function () {
                console.log('message now: ' + JSON.stringify(scope.message));
//                element.show();
//                //noinspection JSUnresolvedFunction
//                $timeout(function () {
//                    //element.empty();
//                    element.fadeOut("slow");
//                }, 2000);
            });
        }
    }
});

Here is my controller

function NotificationController($scope) {
    $scope.message = {};
    console.log('notification activated');

    $scope.invite = function() {
        console.log("submitting invite for " + $scope.email);
        $scope.message.title = 'hello';
//        console.log('message now is ' + JSON.stringify($scope.message, null, 2));
    }
}

Here is how I use it

<form class="pure-form" data-ng-controller="NotificationController">
    <input type="text" class="pure-input-1-2" placeholder="Email"
           data-ng-model="email">
    <button type="submit"
            class="pure-button notice pure-button-xlarge"
            data-ng-click="invite()">Invite me
    </button>
</form>
<notification data-ng-model="message"></notification>

What I want
- Whenever value if scope.message changes in NotificationController, the directive has the new value so that I can alert that on web page

What I do not understand
It seems I am not understanding how $scope.$watch is working

Please help

Upvotes: 1

Views: 920

Answers (2)

Mickael
Mickael

Reputation: 5736

You made several mistakes :

  1. Your notification tag must be inside controller (in html) since it must have access to 'message' variable.
  2. Your binding in your directive is wrong : you must use '=' instead of '@' (as Thalis said).
  3. Variable 'message' does not exist in your directive, you must use scope.ngModel (which is binded to your message variable).
  4. Callback given in your watcher will be executed each time your variable will be updated. Since you use an object, watcher will be executed when your variable reference change. You must set 'true' to your third parameter of your watcher to check for object equality).

Here is your sample :

HTML :

<body>
    <div id="my-app" data-ng-app="myApp">
        <form class="pure-form" data-ng-controller="NotificationController">
            <input type="text" class="pure-input-1-2" placeholder="Email" data-ng-model="email" />
            <button type="submit"
              class="pure-button notice pure-button-xlarge"
              data-ng-click="invite()">Invite me
            </button>
            <notification data-ng-model="message"></notification>
        </form>        
    </div>
</body>

Javascript :

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

myApp.directive('notification', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            ngModel: '='
        },
        template: '<div class="alert fade" bs-alert="ngModel"></div>',
        link: function (scope, element, attrs) {
            scope.$watch('ngModel', function () {
                console.log('message now: ' + JSON.stringify(scope.ngModel));
//                element.show();
//                //noinspection JSUnresolvedFunction
//                $timeout(function () {
//                    //element.empty();
//                    element.fadeOut("slow");
//                }, 2000);
            }, true);
        }
    }
});

myApp.controller('NotificationController', ['$scope', function($scope) {
    $scope.message = {};
    console.log('notification activated');

    $scope.invite = function() {
        console.log("submitting invite for " + $scope.email);
        $scope.message.title = 'hello';
//      console.log('message now is ' + JSON.stringify($scope.message, null, 2));
    };
}]);

See this fiddle : http://jsfiddle.net/77Uca/15/

Upvotes: 2

thalisk
thalisk

Reputation: 7743

I believe that in your directive definition you need:

ngModel: '='

instead of:

ngModel: '@'

If you want to use the '@', your view should be:

<notification data-ng-model="{{message}}"></notification>

Also in your $watch you should be watching for ngModel and not message.

Upvotes: 0

Related Questions