多个指令要求新/隔离范围

我写了一个对话框指令(myPopup),另一个用于拖动这个对话框(myDraggable),但是我总是得到这个错误:

多个指令[myPopup,myDraggable]要求新/隔离范围

这是一个Plunker: http ://plnkr.co/edit/kMQ0hK5RnVw5xOBdDq5P?p=preview

我能做什么?

JS代码:

var app = angular.module('myApp', []); function myController($scope) { $scope.isDraggable = true; } app.directive('myPopup', [ function () { "use strict"; return { restrict: 'E', replace: true, transclude: true, template: '<div my-draggable="draggable"class="dialog"><div class="title">{{title}}</div><div class="content" ng-transclude></div></div>', scope: { title: '@?dialogTitle', draggable: '@?isDraggable', width: '@?width', height: '@?height', }, controller: function ($scope) { // Some code }, link: function (scope, element, attr) { if (scope.width) { element.css('width', scope.width); } if (scope.height) { element.css('height', scope.height); } } }; } ]); app.directive('myDraggable', ['$document', function ($document) { return { restrict: 'A', replace: false, scope: { enabled: '=myDraggable' }, link: function (scope, elm, attrs) { var startX, startY, initialMouseX, initialMouseY; if (scope.enabled === true) { elm.bind('mousedown', function ($event) { startX = elm.prop('offsetLeft'); startY = elm.prop('offsetTop'); initialMouseX = $event.clientX; initialMouseY = $event.clientY; $document.bind('mousemove', mousemove); $document.bind('mouseup', mouseup); $event.preventDefault(); }); } function getMaxPos() { var computetStyle = getComputedStyle(elm[0], null); var tx, ty; var transformOrigin = computetStyle.transformOrigin || computetStyle.webkitTransformOrigin || computetStyle.MozTransformOrigin || computetStyle.msTransformOrigin || computetStyle.OTransformOrigin; tx = Math.ceil(parseFloat(transformOrigin)); ty = Math.ceil(parseFloat(transformOrigin.split(" ")[1])); return { max: { x: tx + window.innerWidth - elm.prop('offsetWidth'), y: ty + window.innerHeight - elm.prop('offsetHeight') }, min: { x: tx, y: ty } }; } function mousemove($event) { var x = startX + $event.clientX - initialMouseX; var y = startY + $event.clientY - initialMouseY; var limit = getMaxPos(); x = (x < limit.max.x) ? ((x > limit.min.x) ? x : limit.min.x) : limit.max.x; y = (y < limit.max.y) ? ((y > limit.min.y) ? y : limit.min.y) : limit.max.y; elm.css({ top: y + 'px', left: x + 'px' }); $event.preventDefault(); } function mouseup() { $document.unbind('mousemove', mousemove); $document.unbind('mouseup', mouseup); } } }; }]); 

从文档 :

应用于相同元素的多个不兼容指令的示例场景包括:

多个指令请求隔离范围

多个指令以相同的名称发布控制器。

使用transclusion选项声明多个指令。

多个指令试图定义一个模板或templateURL。

尝试删除myDraggable指令中的隔离范围:

 app.directive('myDraggable', ['$document', function ($document) { return { restrict: 'A', replace: false, scope: { enabled: '=myDraggable' }, //remove this line 

scope.enabledreplaceattrs.enabled

 if (attrs.enabled == "true") { 

并修改你的模板来绑定启用属性:

 <div my-draggable="draggable" enabled="{{draggable}}" 

DEMO

DOM元素正在与您尝试的隔离范围创build冲突。 因此,你应该总是问自己是否需要隔离范围。

考虑删除myDraggable上的隔离作用域,插入myDraggable值(就像使用isDraggable做的那样),并访问link函数中的属性。

 <div class="draggable" my-draggable="{{isDraggable}}">I am draggable {{isDraggable}}</div> 
 ... replace: false, link: function (scope, elm, attrs) { var startX, startY, initialMouseX, initialMouseY, enabled = attrs.myDraggable === 'true'; if (enabled === true) { ... 

在这里查看更新的Plunker并注意myPopup模板中的更改。

如果您想查看myDraggable属性更改,请执行以下操作:

 attrs.$observe('myDraggable', function(iVal) { enabled = iVal === 'true'; // AND/OR if (iVal === 'true') doSomething(); }); 

请参阅angular度属性文档 $观察function

我遇到了类似的情况。 如果它不会弄乱你的布局,你肯定需要在两个指令上都有隔离作用域,我的build议是从myPopup指令定义中删除属性replace: true

我的错误是类似的:

错误:[$ compile:multidir]多个指令[组,组]请求新/隔离作用域:

在我的情况下,我有重复的声明

  .component('groups', new GroupsComponent()); 

在app.js / app.ts文件中

并同时在组件上

 const groups = angular.module('groups', ['toaster']) .component('groups', new GroupsComponent()); 

从app.js / app.ts中删除它修复了这个问题。

有办法解决这个问题。

您不会隔离该指令的范围,而是使用$ new方法创build一个新的隔离范围。 这个方法创build一个新的子范围,如果你在第一个参数中使用true,它将创build一个隔离的范围:

如果为true,那么作用域不会从父作用域原型inheritance。 范围是孤立的,因为它不能看到父>范围属性。 创build小部件时,小部件不会意外读取父项。

但是这不是问题,因为我们可以通过指令链接函数访问私有范围,所以可以与“父”和隔离范围并行工作成一个隔离范围的指令的非常接近的行为。

下面的例子:

 app.directive('myDraggable', ['$document', function ($document) { return { restrict: 'A', replace: false, scope: false, //scope: { enabled: '=myDraggable', oneWayAttr: "@" }, //Just for reference I introduced a new link: function(parentScope, elem, attr) { var scope = parentScope.$new(true); //Simulated isolation. scope.oneWayAttr = attr.oneWayAttr; //one-way binding @ scope.myDraggable = parentScope.$parent.$eval(attr.myDraggable); scope.watchmyDraggable = function () { return scope.myDraggable = parentScope.$parent.$eval(attr.myDraggable); }; scope.$watch(scope.watchmyDraggable, function(newValue, oldValue) { //(...) }); parentScope.innerScope = scope; //If you need view access, you must create a kind of symbolic link to it. //(...) } 

我开发了这个工作,以validation指令,这是很好的作品。

从你的“myDraggable”中删除范围:{enabled:'= myDraggable'} – 你不需要它。 所以:

  return { restrict: 'A', replace: false, link: function (scope, elm, attrs) { 

当我压缩我的应用程序时,我已经包含了我的指令js文件两次。 这导致了错误。