【问题标题】:If i use my directive more than once, attribute always takes last assigned value如果我多次使用我的指令,属性总是取最后一个赋值
【发布时间】:2019-02-12 16:36:50
【问题描述】:

下面我正在使用我的自定义指令type-ahead-custom一个接一个。

第一次type-ahead-custom="maps" 第二次type-ahead-custom="maps1"

如果我在指令中访问属性type-ahead-custom 值,它总是返回“maps1”。我该如何解决这个问题?

这里是 plunker:https://plnkr.co/edit/hXlNJKboSlA2lAvRqYF1

<form class="form-horizontal" ng-controller="myCtrl" >
  <div class="form-group">
    <div>
      <label for="account" class="col-sm-2 col-md-2 control-label customize-label ">Typeahead 1</label>
      <div class="col-sm-8">
        <div class="inner-addon right-addon">

          <input type="text" ng-model="selectedOptions.planes" uib-typeahead="plane as plane.formatted_address for plane in search($viewValue)" type-ahead-custom="maps" typeahead-loading="loadingdata" typeahead-no-results="noResults" class="form-control ng-valid ng-dirty ng-valid-parse ng-touched" aria-autocomplete="list" aria-expanded="false" aria-owns="typeahead-4-8758" />
        </div>
      </div>
    </div>
  </div>

        <div class="form-group">
    <div>
      <label for="account" class="col-sm-2 col-md-2 control-label customize-label ">Typeahead 2</label>
      <div class="col-sm-8">
        <div class="inner-addon right-addon">

          <input type="text" ng-model="selectedOptions.plants" uib-typeahead="plane as plane.formatted_address for plane in search($viewValue)" type-ahead-custom="maps1" typeahead-loading="loadingdata" typeahead-no-results="noResults" class="form-control ng-valid ng-dirty ng-valid-parse ng-touched" aria-autocomplete="list" aria-expanded="false" aria-owns="typeahead-4-8758" />
        </div>
      </div>
    </div>
  </div>
</form>

// 代码在这里

var exampleApp = angular.module('exampleApp', ['ui.bootstrap']);

exampleApp.directive('typeAheadCustom', function($http, $q) {
return {
    link: function($scope, $element, $attributes) {


        $scope.search = function(newValue) {

           console.log($attributes.typeAheadCustom);
         var dfr = $q.defer();
         $http.get('//maps.googleapis.com/maps/api/geocode/json', {
             params: {
                 address: newValue,
                 sensor: false
                 }
           }).success(function(data) {

              dfr.resolve(data.results);

          });

          return dfr.promise;
        };
    }
}
});

exampleApp.controller('myCtrl', function($http,$scope) {
  $scope.selectedOptions = {};
});

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    问题是你没有为你的指令创建一个新的范围,基本上它们在任何地方都共享相同的范围。

    因此,当您注册指令的第一个实例时,$scope.search 方法会在与 $attributes.typeAheadCustommap 相同的范围内创建。

    在第二条指令执行时,它会覆盖旧的 $scope.search 方法,该方法由 1st directive 实例创建,并且 $attributes.typeAheadCustom 的值为 map1

    这就是为什么当你调用 search 方法时,它总是有最新的 $attributes.typeAheadCustom 值。

    为了解决您的问题,我建议您使用隔离范围创建指令。这意味着指令将有自己的新范围。因此,无论您将指令放置在何处,都不会出现此类问题,并且指令将充当单独的组件,无论您何时在同一页面上实例化它。

    现在您的指令范围与放置指令的页面范围不同,因此您无法访问指令内的控制器值,您需要使用内部隔离的scope: { ... } 绑定传递所需的值。

    【讨论】:

    • 谢谢......如果我做隔离范围......我仍然能够从 uib-typeahead 启动搜索功能
    • @whippits 更好的提示是......仅在指令模板内移动 ui-typeahead ......并使用 scope: { ... } 将值从外部世界传递到指令隔离范围
    【解决方案2】:

    由于指令的实例化与其他指令共享作用域,因此根据指令的属性值将函数添加到作用域。

    var exampleApp = angular.module('exampleApp', ['ui.bootstrap']);
    
    exampleApp.directive('typeAheadCustom', function($http, $q) {
    return {
        link: function(scope, elem, attrs) {
            //create object on scope
            scope[attrs.typeAheadCustom] = {};
            var vm = scope[attrs.typeAheadCustom];
            //put function on object 
            vm.search = function(newValue) {
                var message=attrs.typeAheadCustom +
                            '=' + newValue;
                console.log(message);
                //
                //Do more stuff
            };
    
        };
    });
    

    因此不同实例化的搜索函数有不同的名称。

     <input type="text" ng-model="selectedOptions.planes" 
         type-ahead-custom="maps1"
         uib-typeahead="plane as plane.formAddress for plane 
                        in maps1.search($viewValue)"
     >
    
     <input type="text" ng-model="selectedOptions.planes" 
         type-ahead-custom="maps2"
         uib-typeahead="plane as plane.formAddress for plane 
                        in maps2.search($viewValue)"
     >
    

    【讨论】:

    • 您创建新范围变量的任何方式,那么为什么不建议使用隔离范围呢?
    猜你喜欢
    • 2012-06-12
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 2015-05-25
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多