angularjs:具有隔离范围和传递参数的自定义指令

时间:2014-11-24 15:52:37

标签: angularjs

我在angularjs中创建了一个带有隔离范围和传递参数的自定义指令。 我尝试检查指令的控制器/链接中的参数,因为有时参数是一个数组,我只需要一个项目。但这不起作用(未定义的对象)。

- 我的指示:

directives.directive('dir.displaytaxoname',  function () {
    return {
       restrict: 'E',
       replace: true,
       scope: {
          dfamily: '@' ,
          dgenus: '@',
          dsn: '@'               
       },
       controller: function ($scope) {

          console.log($scope.dsn); // empty string in the console but ok in the rendered view 
          /*function tools_isArray(arr) { return ( arr instanceof Array ); }*/
          // if the dfamily argument is an array i just want the first item 
          if(tools_isArray($scope.dfamily)){ $scope.dfamily = $scope.dfamily[0]; }
          if(tools_isArray($scope.dgenus)){ $scope.dgenus = $scope.dgenus[0]; }
          if(tools_isArray($scope.dsn)){ cl("indsn") ;  $scope.dsn = $scope.dsn[0]; }
       },
       templateUrl: "partials/elements/displaytaxoname.html"
    }
 });

- 我的模板:

<span>
    {{dfamily}}&nbsp;<i ng-show="dgenus!=''">{{dgenus}}&nbsp;</i><i>{{dsn}}</i><br>
</span>

- 调用指令:

<dir.displaytaxoname dfamily="{{specimen['T_FAMILY']}}" 
                     dgenus="{{specimen['T_GENUS']}}" 
                     dsn="{{specimen['T_SCIENTIFICNAME']}}">
</dir.displaytaxoname>

我尝试使用链接/控制器进行多次组合但不起作用。 我该怎么办?

感谢

3 个答案:

答案 0 :(得分:2)

如果要将非字符串值传递给指令,则需要直接绑定到外部作用域表达式,而不是属性值(see documentation),因为属性值始终为String

此外,如果您不是100%确定编译指令时外部作用域上的数据已经存在,则需要$watch数据而不是仅使用初始值。

scope: {
    dfamily: '=',    // bind to expression instead of attribute value
    // ...
},
controller: function ($scope) {
    // watch property value changes instead of using just the initial value
    $scope.$watch('dfamily', function (value) {
        if (tools_isArray(value)) {
            // be extremely careful not to create an infinite cycle here
            // (better save the modified values to different variables)
            $scope.dfamily = value[0];
        }
    });
    // ...
}

<tag dfamily="specimen['T_FAMILY']" ...></tag>

答案 1 :(得分:1)

您已使用=?

进行了测试
scope: {
          dfamily: '=' ,
          dgenus: '=',
          dsn: '='               
       }

答案 2 :(得分:0)

[基于@ hon2a答案的完整工作解决方案]

这是一个带有隔离范围的指令,它在参数中取一个数组。 它使用$ watch,因为在主控制器中的异步调用之后提供了数组参数

- 主控制器:

// in a asynchronus call to elasticsearch
  elasticsearch.search({
     index: $index,
     size:1,
     body: {
        "query": $query
     }
  }).then(function (response) {
     $scope.specimen = response.hits.hits[0]["_source"];
     $scope.taxonamedata = {
        "T_FAMILY" : $scope.specimen["T_FAMILY"] ,
        "T_GENUS": $scope.specimen["T_GENUS"],
        "T_SCIENTIFICNAME": $scope.specimen["T_SCIENTIFICNAME"], //scientific name
        "D_IDENTIFIEDBY": $scope.specimen["D_IDENTIFIEDBY"],
        "D_CREATED":$scope.specimen["D_CREATED"]
     } ;
   }
....

- 调用指令:

<dir.displaytaxoname data="taxonamedata"></dir.displaytaxoname>

- 指令:

 directives.directive('dir.displaytaxoname',  function ($filter) {
   return {
      restrict: 'E',
      replace: true,
      scope: {
         data: '='
      },
      controller: function ($scope) {
         // watch property value changes instead of using just the initial value
         $scope.display = "";
         $scope.$watch('data', function (value) {
            if(tools_defined(value)){
               var tmp = value; // copy it to tmp variable to avoid loop when change
               for (var v in tmp) {
                  if (tools_isArray(tmp[v])) { // convert all the array to string
                     tmp[v] = tmp[v][0];
                  }
               }
               $scope.display = tmp["T_FAMILY"] + '&nbsp;';
               if (tools_defined(tmp["T_GENUS"])) {
                  $scope.display += '<i>' + tmp["T_GENUS"] + '</i>&nbsp;';
               }
               if (tools_defined(tmp["T_SCIENTIFICNAME"])) {
                  $scope.display += '<i>' + tmp["T_SCIENTIFICNAME"] + '</i><br>';
               }
               $scope.display += tmp["D_IDENTIFIEDBY"] ;
               if (tools_defined(tmp["D_CREATED"])) {
                  $scope.display +=  '&nbsp;('+$filter('date')(tmp["D_CREATED"], "dd/MM/yyyy")+')';
               }
            }

         });
      },
      plain:true,
      template: '<span ng-bind-html="display | unsafe"></span>'
   }
});

- 显示hmtl:

的不安全过滤器
interfaceApp.filter('unsafe', function ($sce) {
   return function (val) {
       return $sce.trustAsHtml(val);
   };
});

function tools_isArray(arr) {
   return ( arr instanceof Array );
}

function tools_defined(object){
   return (( typeof object != undefined) && ( typeof object != "undefined") && ( object != null ) ) ;
}