简体   繁体   English

将变量传递给指令AngularJS中的动态Controller

[英]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 : 模板中 (例如,views / myservice.html),我加载了控制器

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

And in the controller (myCtrl) I access to the patient and service this way: 在控制器(myCtrl)中,我以这种方式访问 患者并进行服务

  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. 这工作正常,但我不喜欢这种通过$ 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. 您可以为patientservice属性创建包装对象。 That can be named as model & then provide that model object to your directive. 可以将其命名为model ,然后将该模型对象提供给您的指令。

Then problem with your current approach is, ng-include create a child scope for template which it renders in it. 然后,当前方法的问题是, ng-include为其创建template的子范围。 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. 它失去了绑定,这就是为什么倾向于使用$parent.$parent符号完全绑定到原始源对象的原因。

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

By making above object structure will ensure you're following Dot Rule . 通过创建上述对象结构,可以确保您遵循Dot Rule Usage of Dot Rule will avoid $parent.$parent explicit scope annotation. Dot Rule将避免$parent.$parent显式范围注释。

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. 除了点规则以外,针对这种范围界定问题的另一种选择是遵循controllerAs模式。 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. 但是接下来,您bindToController: true controllerAs使用隔离scope ,因此应将bindToController: true选项设置为true,以确保将所有scope合并到控制器上下文中。

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

And then use $ctrl before each directive scoped variable. 然后在每个指令作用域变量之前使用$ctrl

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). 您应该使用services并将变量存储在这些服务中(在这种情况下,您应该创建一个工厂来存储数据)。 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. 旁注:您可以在指令中使用{ ..., controller: 'controllerName', controllerAs: 'vm' }语法,因此您无需在html中声明它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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