Search code examples
angularjsangularjs-directiveangularjs-watch

Change ngModel that was assigned to a directive on a callback from that directive


So I have my SPA application.

Here on plunker (I'll not paste all the code, as it is too much) you can see the it's parts recreation (the structure and the hierarchy are the same).

Where did the problem started... By the design doc, On one of the pages we have a link to a policy documentation and a checkbox for a client to check, that he did read it.

By design:

  1. Checkbox is always enabled, so client could always attempt to check it
  2. After the client opens the policy documentation (click on the link), the checkbox should turn checked when client is clicking on it
  3. If client didn't opened the (clicked) the policy documentation link yet and tries to check the checkbox, it return to be not checked at the moment he releases the mouse, and relevant error message should be shown

UPDATED:

Thanks to Rafaeelloo and Kobi Cohen I could get the code simplified a lot, and to get rid of the watches, and useless stuff...

For now this is what I have...

Here is the directive controller:

app.directive('checkBox', [function() {
  var directive = {
    scope: {}, 
    restrict: 'E', 
    controller: function() {},
    controllerAs: 'checkBoxCtrl',
    bindToController: {
      ngModel: '=',
      callback: '&callback',
      text: '@' 
    },
    templateUrl: 'check-box.directive.view.html',
    link: function() {},
    require: 'ngModel'
  };
  return directive;
}]);

And directive html:

<div class="checkboxContainer">
    <label class="btn btn-checkbox" ng-class="{'active': checkBoxCtrl.ngModel}" 
                                    ng-click="checkBoxCtrl.ngModel = !checkBoxCtrl.ngModel; checkBoxCtrl.callback()">
        <span class="checkboxPic"></span> 
        <span class="checkboxText">{{checkBoxCtrl.text}}</span> 
    </label>
</div> 

Here is view html:

<check-box text="check me"  ng-model="viewCtrl.checkBoxResult" 
                            callback="viewCtrl.callback()"></check-box>
<br/>
<a ng-click="viewCtrl.openGoogleClicked = true" href="//www.google.com" target="_blank">Open Google</a>
 
<hr> 

<h3>Status</h3>  
check box result: {{viewCtrl.checkBoxResult}}    
<br/>
google opened: {{viewCtrl.openGoogleClicked}}
<br/>
callback function called: {{viewCtrl.callbackCalled}}

And this is view controller:

angular.module('app').controller('viewController', ['$scope', function($scope) {
  this.checkBoxResult;
  this.openGoogleClicked;
  this.callbackCalled;
 
  this.callback = function callback() {  
    this.callbackCalled = true;
    if (this.checkBoxResult && angular.isUndefined(this.openGoogleClicked)) {
      this.checkBoxResult = false;
    } 
  };
}]);

The question/problem/opened question: Callback is called before the ngModel of the view controller had been changed. So it doesn't really meter if I change it back to false within the callback, or not, as after a callback the directive (as I understand) still binds the new value to it.

Is there a cure to this?


Solution

  • Depending on what you're trying to do, you may do it like here (here) or you can write validator that has function to determine validity (here is example of writing your own validator) then your form and checkbox will have invalid what is in my opinion better than disallowing user to check the checkbox