scope variable inside directives not changing

2,859 views
Skip to first unread message

Prashish Rajbhandari

unread,
May 17, 2013, 4:01:07 PM5/17/13
to ang...@googlegroups.com
I defined a scope variable ($scope.english_month_year) to 'testing' inside the controller for testing purpose. The scope variable's value is changed when a button is pressed i.e. calls the function ADtoBS();

The value of $scope.english_month_year is 'testing' when the directive loads for the first time but when I press the button, which changes the scope variable's value, the new scope variable changes (seen by {{english_month_year}}) but the scope variable inside the directive doesn't change. Can anyone tell me how I can solve this issue.

Controller:
angular.module('Calendarapp.controllers',[])
  .controller('nepaliCalendarCtrl', function($scope, $element) {

  $scope.english_month_year = "testing";

  $scope.ADtoBS = function() {
      $scope.english_month_year = nepengMonth[$scope.selectedEngMonth];
      $scope.nepali_month_year = changeTonep($scope.selectedEngMonth, String($scope.selectedEngYear));
  };
});

Directive:
angular.module('Calendarapp.directives', [])
  .directive('nepCalendar', function() {
    return {
      restrict: 'E',
      link: function($scope, element, attrs)
      {
        $scope.$watch($scope.english_month_year, function() {
        element.replaceWith('<nep-calendar>' +
          $scope.english_month_year + '</nep-calendar>');

        });
      }
    }
  });

{{english_month_year}}
<nep-calendar></nep-calendar>


James Muir

unread,
May 17, 2013, 10:53:58 PM5/17/13
to ang...@googlegroups.com
Caveat : I am just a beginner at Angular. It seems that your $scope is being used as a model. You should look at scope as a reference to assign models to. So where you have  

$scope.english_month_year

Try 

 $scope.data.english_month_year

Where data is your model. From my understanding when you are updating    $scope.english_month_year   you are updating the reference which invalidates the two way binding. When you use  $scope.data.english_month_year  you are updating the value of the model. 

The other part is that, in a directive, the scope is isolated to the element that the directive is declared on, and any child tags of that element. It does not inherit from, or communicate with, the parent (in your case nepaliCalendarCtrl) unless you tell it to. This can be done by declaring a scope attribute in the directive and assigning a bind pattern. Specifically


scope - If set to:

  • true - then a new scope will be created for this directive. If multiple directives on the same element request a new scope, only one new scope is created. The new scope rule does not apply for the root of the template since the root of the template always gets a new scope.

  • {} (object hash) - then a new 'isolate' scope is created. The 'isolate' scope differs from normal scope in that it does not prototypically inherit from the parent scope. This is useful when creating reusable components, which should not accidentally read or modify data in the parent scope. 
    The 'isolate' scope takes an object hash which defines a set of local scope properties derived from the parent scope. These local properties are useful for aliasing values for templates. Locals definition is a hash of local scope property to its source:

    • @ or @attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr="hello {{name}}"> and widget definition ofscope: { localName:'@myAttr' }, then widget scope property localName will reflect the interpolated value of hello {{name}}. As the name attribute changes so will the localName property on the widget scope. The name is read from the parent scope (not component scope).

    • = or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr="parentModel"> and widget definition of scope: { localModel:'=myAttr' }, then widget scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected inlocalModel and any changes in localModel will reflect in parentModel.

    • & or &attr - provides a way to execute an expression in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr="count = count + value"> and widget definition of scope: { localFn:'&myAttr' }, then isolate scope property localFn will point to a function wrapper for the count = count + valueexpression. Often it's desirable to pass data from the isolated scope via an expression and to the parent scope, this can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22})






Reply all
Reply to author
Forward
0 new messages