SteveP124
SteveP124

Reputation: 73

Angular Custom directive change attribute value

Struggling to find out the best way to watch for attribute changes, which would ideally update based on a keypress event, bound to the scope in the parent controller

I would like each 'instance' of the directive to have its own 'hasFocus' property to be changed by updating the attribute value e.g.

<menu has-focus="{{ true }}" ></menu>
<menu has-focus="{{ false }}" ></menu>
<menu has-focus="{{ false }}" ></menu>

template:

<div class="menu">
<ul>
    <li ng-repeat="option in menu.options" ng-class="{ 'focused' : hasFocus  }" tabindex="{{ $index }}">
        <div class="icon">{{ $index+1 }}</div>
    </li>
</ul>

and so only 1 directive can have the value equal to 'true' at any one time.

I have a custom directive

.directive('menu', function()
{
  restrict : 'E',
  templateUrl : 'partials/menu-left.html',
  replace : true,
  scope : {
        hasFocus : '@'
  },
  link : function( $scope, element, attrs )
  {
    attrs.$observe('hasFocus', function(value) {
        console.log(value);
     });
  }

}) 

but cant seem to extract the value from the $observe method tried using $watch but still didnt work not sure what I am doing wrong!

Upvotes: 7

Views: 8186

Answers (1)

benri
benri

Reputation: 161

if you use the @ binding, you might have to use $watch like this:

$scope.$watch(function(){
   return attrs.hasFocus;
}, function(val) {
     $scope.hasFocus = val;
});

if that doesn't work, or if you prefer two-way binding with =:

<menu has-focus="true" ></menu>

and

.directive('menu', function()
{
  restrict : 'E',
  templateUrl : 'partials/menu-left.html',
  replace : true,
  scope : {
        hasFocus : '='
  },
  link : function( $scope, element, attrs )
  {
    // $scope.hasFocus holds true/false
  }

}) 

I think two-way binding is better especially with booleans because if you only need it to control how the DOM looks, you might not even need to watch for a change, you'd just have to plug in $scope.hasFocus into the DOM somewhere (ng-show, ng-switch, etc.)

EDIT: yes, I just noticed your template, so if you use two-way binding (=) you don't need the watch

Upvotes: 2

Related Questions