3

In my controller, I have the following array of users, which will be displayed by iteration in the partial html template

in controller:

vm.users = [
      {"username": "johnDoe", "address": "Saltlake City, UT", "age": 34},
      {"username": "janeDoe", "address": "Denver, CO", "age": 33},
      {"username": "patrickDoe", "address": "San Francisco, CA", "age": 35}
    ];

partial html code:

<div ng-repeat="user in mapView.users">
<my-customer info="user"></my-customer></div>

myCustomer directive: I wish to increment the customer's age when the mouseover event happens on the customer. Is it possible to do this in the directive?

angular
    .module('angularApp')
    .directive('myCustomer', function() {

  return {
    restrict: 'E',
    link: function(scope, element) {
      element.bind('mouseover', function(e) {
        e.target.age++; // this is not working, need help here!
        console.log(e.target, 'mouseover');
      });
    },
    scope: {
      customerInfo: '=info'
    },

    templateUrl: 'views/directives/myCustomer.html'
  };

}); //myCustomer

myCustomer template:

<span>
  <label class="label-success">Username: {{customerInfo.username}}</label>
</span>
  <span>
    <label class="label-default">{{customerInfo.address}}</label>
  </span>
  <span>
    <label class="label-danger">{{customerInfo.age}}</label>
  </span>

2 Answers 2

4

The more "Angular" way of doing things would be to use ng-mouseover

You could put it in the "partial html" view

<my-customer 
    info="user"
    ng-mouseover="user.age = user.age + 1;"></my-customer>

ng-mouseover evals the expression within the Angular context. This ensures everything is within the Angular context and you never have to worry about triggering digests manually.

https://docs.angularjs.org/api/ng/directive/ngMouseover

per @floriban

You could also put it within the directive template itself

<div ng-mouseover="customerInfo.age = customerInfo.age + 1;">
  <span>
    <label class="label-success">Username: {{customerInfo.username}}</label>
  </span>
  <span>
    <label class="label-default">{{customerInfo.address}}</label>
  </span>
  <span>
    <label class="label-danger">{{customerInfo.age}}</label>
  </span>
</div>
Sign up to request clarification or add additional context in comments.

6 Comments

Side note: this will trigger a scope.$apply on every mouse over. If you don't need to update the DOM everytime, a custom listener is still more performant. Also, OP suggests that the mouse over is part of the directive logic, so it should be in the directive template rather than here (which forces the user to do that every time he uses the directive)
Triggering an $apply on every mouseover is typically the desired behavior, without it you won't have a guarantee of 2-way binding. Which can indeed be less performant in some edge cases I suppose, good call out.
thanks, but got this error: Error: [$parse:syntax] Syntax Error: Token 'undefined' not a primary expression at column null of the expression [user.age++] starting at [user.age++].
ng- prefixed attributes evaluate what are considered "AngularJS Expressions". I guess ++ is not a valid operator in AngularJS expressions, switch it to user.age = user.age + 1.
yes, exactly user.age = user.age + 1 works for me. When I use user.age++, the IDE I am using complains that's a syntax error. It's all good now. thank you guys so much :)
|
1

e.target is the HTML element on which you have mouseovered. Use the real user info instead:

element.bind('mouseover', function(e) {
   scope.customerInfo.age++;
});

Altermatively you can do everything in the HTML using the build-in ng-mouseover directive. In views/directives/myCustomer.html:

<div ng-mouseover="customerInfo.age++"> ... content of the template </div>

NB: you may prefer ng-mouseenter to not fire the event on every pixel you mouse over, but just when you enter the zone with your mouse.

5 Comments

thanks, the 'scope.customerInfo.age++' does not seem working in my testing, I guess the 'age' is not bound to the view.
what do you see when you console.log scope.customerInfo and scope.customerInfo.age? It should be here since it is bound with your directive
got this error: at Parser.logicalOR (localhost:9000/bower_components/angular/angular.js:12209:21) <div ng-mouseover="customerInfo.age++">
For now remove the ng-mouseover and use the first solution that I wrote to understand what is wrong: in the mouseover callback, log what is in scope.customerInfo
thanks again. the customerInfo.age++ does not work for me, but the element.bind() way you provided works well!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.