6
votes

I'm trying to write a directive to create a map component so I can write something like:

<map></map>

Now the directive looks like this:

angular.module('myApp')
  .directive('map', function (GoogleMaps) {
    return {
      restrict: 'E',
      link: function(scope, element, attrs) {
        scope.$watch('selectedCenter', function() {
          renderMap(scope.selectedCenter.location.latitude, scope.selectedCenter.location.longitude, attrs.zoom?parseInt(attrs.zoom):17);
        });

      function renderMap(latitude, longitude, zoom){
          GoogleMaps.setCenter(latitude, longitude);
          GoogleMaps.setZoom(zoom);
          GoogleMaps.render(element[0]);
      }
    }
  };
});

The problem is that 'watch' inside the directive doesn't looks very well thinking in the reusability of the component. So I guess the best thing is being able to do something like:

<map ng-model="selectedCenter.location"></map>

But I don't know if it's even a good thing using angular directives inside custom directives or how can I get the object indicated in the ng-model attribute in the custom-directive's link function.

3

3 Answers

4
votes

You will need to do something like that

angular.module('myApp')
  .directive('map', function (GoogleMaps) {
    return {
      restrict: 'E',
      scope: {
        ngModel: '=' // set up bi-directional binding between a local scope property and the parent scope property 
      },

as of now you could safely watch your scope.ngModel and when ever the relevant value will be changed outside the directive you will be notified.

Please note that adding the scope property to our directive will create a new isolated scope.

You can refer to the angular doc around directive here and especially the section "Directive Definition Object" for more details around the scope property.

Finally you could also use this tutorial where you will find all the material to achieve a directive with two way communication form your app to the directive and opposite.

2
votes

Without scope declaration in directive:

html

<map ng-model="selectedCenter"></map>

directive

app.directive('map', function() {
    return {
        restrict: 'E',
        require: 'ngModel',
        link: function(scope, el, attrs) {              
            scope.$watch(attrs.ngModel, function(newValue) {
                console.log("Changed to " + newValue);
            });                 
        }
    };
});
1
votes

One easy way you can achieve this would be to do something like

<map model="selectedCenter"></map>

and inside your directive change the watch to

scope.$watch(attrs.model, function() {

and you are good to go