0

I have a class written in ES6 and I have a directive "action" which needs to access a controller value called "selected". This controller value "selected" is updated by another directive "grid". ( 2 way binding)

I need to pass "selected" value from the controller that has been updated by Directive "grid" to Directive "actions" on-select . I have tried to pass by doing a "bind" but i get an type error as "cannot read actionHandler of undefined"

I am not sure what is the best way to handle this , such that when the "selected" value has been updated by the "grid" directive, the actionEvent is triggered with the updated value from the controller. The directives are working correctly and i am able to see that it breaks on breakpoints.

Here is what i have in HTML

<div class="col-xs-9">          
   <action options="ctrl.Actions" on-select="ctrl.actionEvent">
   </action>
</div>
<div class="col-xs-12">
  <grid config="ctrl.gridOptions" data="ctrl.data" selected="ctrl.selected"></grid>
 </div>

In the Controller,

 class CheckC {
   constructor($scope) {
    this.$scope = $scope;       
    this.selected = this.$scope.selected;
  }

actionEvent() {
    this.actionHandler.bind(this);
}

actionHandler(item, event) {
    let selection;
    let model = this.selected;
    if(model) {
        item.id = 1;
    }
 }
 }
looneytunes
  • 741
  • 4
  • 16
  • 35
  • Try to log `this` inside `actionEvent` function, what it will show? – Kanso Code Sep 15 '16 at 07:30
  • _"The directives are working correctly"_ But not as they should. `on-select` should expect an expression like `ctrl.actionEvent()`. That would also solve your problem. – a better oliver Sep 15 '16 at 09:17
  • Re-assign the bound methods to the class instance in your constructor: `this.actionHandler = this.actionHandler.bind(this)`. Just calling `this.actionHandler.bind(this)` in `actionEvent` does not invoke the method, simply creates a new function that is discarded when `actionEvent` exits as the bound method is not referenced by anything. – sdgluck Sep 15 '16 at 10:10

1 Answers1

4

First of all, don't be confused between .bind() and .call().

  • First returns a new function instance, that can be called later, but with preserved this.
  • Second calls function immediately, but modifies context of this only for this call.

Read this answer for more information

You are passing a reference to actionEvent method. At the moment of call, the reference to original controller object is already lost.

To preserve the reference, you need to save it first in constructor

class CheckC {
  constructor($scope) {
    this.$scope = $scope;       
    this.selected = this.$scope.selected;
    //bind method here
    this.actionEvent = this.actionEvent.bind(this);
  }

  actionEvent(item, event) {
    // this here will be always contain a referene to class instance
    this.actionHandler(item, event);
  }

  actionHandler(item, event) {
    let selection;
    let model = this.selected;
    if(model) {
      item.id = 1;
    }
  }
}

Also in your code actionEvent method seems redundant. Consider to recfactor code and pass actionHandler directly. (Bu don't forget to update .bind() call, it should bind actionHandler after).

Community
  • 1
  • 1
just-boris
  • 9,468
  • 5
  • 48
  • 84