简体   繁体   中英

Pass variables to a dynamic Controller inside a Directive AngularJS

I got a directive that loads a different template depending on the variable type that is passed to it. I pass to the isolated scope of the directive the variables patient and service too.

.directive('serviceCharts', serviceCharts);

function serviceCharts() {
  return {
    restrict: 'E',
    link: function (scope, element, attrs) {
      if(attrs.type) {
         scope.template = 'views/' + type + '.html';
    }
    attrs.$observe('type', function (type) {
      if(attrs.type) {
        scope.template = 'views/' + type + '.html';
      }
    });
  },
  template: '<div ng-include="template"></div>',
  scope:{
    patient:'=',
    service:'='
  }
};

}

In the template (views/myservice.html for example) I load the controller :

 <div ng-controller="myCtrl as vm"> 
     VIEW
 </div>

And in the controller (myCtrl) I access to the patient and service this way:

  service = $scope.$parent.$parent.service;
  patient = $scope.$parent.$parent.patient;

This works fine, but I don't like this way of accessing the variables via the $parent.$parent. This is messing with my tests too.

Is there another (better) way to do this?

Thank you!

You could create a wrapper object for patient & service properties. That can be named as model & then provide that model object to your directive.

Then problem with your current approach is, ng-include create a child scope for template which it renders in it. So as your passing primitive type object binding to directive, If you are changing any of child primitive type binding in child scope. It loses a binding that's why tend to using $parent.$parent notation exactly bind to original source object.

$scope.model = {
  patient:'My Patient',
  service:'My Service'
};

By making above object structure will ensure you're following Dot Rule . Usage of Dot Rule will avoid $parent.$parent explicit scope annotation.

Directive scope binding will changed down to below

scope:{
   model:'='
}

And directive usage will look like below

<service-charts type="{{'sometype'}}" model="model"></service-charts>


The other alternative than Dot Rule to such kind of scoping related issue is follow controllerAs pattern. But then as you are gonna use isolated scope with controllerAs you should make bindToController: true option to true for making sure all the scope are merged down to controller context.

scope:{
    patient:'=',
    service:'='
},
controllerAs: '$ctrl',
bindToController: true

And then use $ctrl before each directive scoped variable.

Yes, there is a better way to do this. You should use services and store variables in those services (in your case you should create a factory for storing data). Then you can inject those services and access their data.

Sidenote: You can use { ..., controller: 'controllerName', controllerAs: 'vm' } syntax in your directive so you do not need to declare those in your html.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM