相同角度指令的多个实例弄乱了范围变量 [英] Multiple instance of same angular directive mess up scope variables

查看:66
本文介绍了相同角度指令的多个实例弄乱了范围变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在类似的页面上多次使用该指令

I am using the directive multiple times on the page like

<div data-escape-amp-curation-multi-value-selector
         data-binding-path="model"
         data-search-key="journeys"
         data-current-selection-model="model.journeys">
    </div>

<div data-escape-amp-curation-multi-value-selector
         data-binding-path="model"
         data-search-key="targets"
         data-current-selection-model="model.targets">
    </div>

我的指令看起来像

var directive : ng.IDirective = {
  restrict : 'A',
  template : '<select multiple="multiple" data-options="sources/>',
  compile() {
    return {
      pre(scope : any, element : any, attrs : any) {
        scope.readonly = attrs.readonly === 'true';
      },
      post(scope : any, element : any, attrs : any) {
        var binder = $parse(attrs.currentSelectionModel),
        valueDropDown = element.find('select.value-dropdown'),
        kendoMultiSelect = valueDropDown.data('kendoMultiSelect'),
        defer = $q.defer();

        /**
         * The method to do search.
         * @type {void}
         */
        scope.doSearch = () =  > {
          scope.showSpinner = true;
          scope.$evalAsync(() =  > {
              if (!cache) {
                metadataService.getMetadata(attrs.searchKey).then(
                  result =  > {
                    cache = result;
                    scope.sources = result;
                    defer.resolve();
                  },
                  error =  > {
                    defer.reject(error);
                  });
              } else {
                scope.sources = cache;
                defer.resolve();
              }

              defer.promise.then(() =  > {
                  kendoMultiSelect.setDataSource(scope.sources);
                  scope.showSpinner = false;
                  kendoMultiSelect.value(binder(scope));
                });
            });
        };

        kendoMultiSelect.bind('change', () =  > {
            binder.bind(scope, kendoMultiSelect.value());
          });

        /**
         * Set cache to null on location change
         */
        scope.$on(LOCATION_CHANGE_START, () =  > {
            cache = null;
          });

        scope.$watch(() =  > scope.$eval(attrs.currentSelectionModel), () =  > {
            if (!scope.sources) {
              if (angular.isDefined(cache) && cache !== null) {
                $timeout(() =  > {
                    scope.sources = cache;
                    kendoMultiSelect.setDataSource(scope.sources);
                    kendoMultiSelect.value(binder(scope));
                  });
              } else {
                scope.doSearch();
              }

            } else {
              kendoMultiSelect.setDataSource(scope.sources);
              kendoMultiSelect.value(binder(scope));
            }
          });
      }
    }
  }
}

当此代码呈现时,它会调用后端服务以根据搜索键填充源,但是bot实例的scope.sources获得相同的值. 它获取上一次搜索服务调用的值. 我在这里想念的是什么? 谢谢.

When this code renders it gives call to backend service to populate sources based on the search key but scope.sources for bot instance gets the same value. It gets the value of last search service call. What I am missing here? Thanks.

推荐答案

scope 原型是在Angular中继承的,但是仅在您请求时创建新的作用域.在这种情况下,您只需装饰您的指令所在的父级定义的现有作用域即可.

scope is prototypically inherited in Angular, but a new scope is only created if you request it. In this case, you are simply decorating the existing scope defined by the parent that your directive is sitting in.

这意味着添加到范围的所有内容都将被同一指令覆盖.

This means that anything added to scope will be overwritten by the same directive.

您可以通过简单地将scope:true属性添加到指令定义对象来告诉指令创建新的作用域:

You can tell your directive to create a new scope by simply adding the scope:true property to your directive definition object:

{
  restrict : 'A',
  scope:true
  //more stuff
}

这是一个简单的示例,以显示创建新作用域的指令与未创建新作用域的指令之间的区别.

Here is a simple example to show the difference between a directive that creates a new scope, and one that does not.

(function() {
  'use strict';

  function NoNewScope() {
    return {
      restrict: 'A',
      template: [
        '<div class="form-group">',
        '  <label>Name - <code>{{name}}</code></label>',
        '  <input class="form-control" type="text" ng-model="name" />',
        '</div>'
      ].join(''),
      link: function(scope) {
        scope.name = "No New Scope";
      }
    };
  }

  function NewScope() {
    return {
      restrict: 'A',
      scope: true,
      template: [
        '<div class="form-group">',
        '  <label>Name - <code>{{name}}</code></label>',
        '  <input class="form-control" type="text" ng-model="name" />',
        '</div>'
      ].join(''),
      link: function(scope) {
        scope.name = "New Scope";
      }
    };
  }

  angular.module('my-app', [])
    .directive('noNewScope', NoNewScope)
    .directive('newScope', NewScope);

}());

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>

<div ng-app="my-app" class="container">

  <div class="row">
    <div class="col-xs-6">
      <h3>NO new scope</h3>
      <div no-new-scope></div>
      <div no-new-scope></div>
    </div>
    <div class="col-xs-6">
      <h3>NEW scope</h3>
      <div new-scope></div>
      <div new-scope></div>
    </div>
  </div>

</div>

这篇关于相同角度指令的多个实例弄乱了范围变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆