Várias diretivas solicitando escopo novo / isolado

Eu escrevi uma diretiva para diálogos (myPopup) e outra para arrastar esta checkbox de diálogo (myDraggable), mas sempre recebo o erro:

Várias diretivas [myPopup, myDraggable] solicitando escopo novo / isolado

Aqui está um Plunker: http://plnkr.co/edit/kMQ0hK5RnVw5xOBdDq5P?p=preview

O que eu posso fazer?

Código 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: '
{{title}}
', 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.min.x) ? x : limit.min.x) : limit.max.x; 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); } } }; }]);

De docs :

Cenários de exemplo de várias diretivas incompatíveis aplicadas ao mesmo elemento incluem:

Várias diretivas solicitando escopo isolado .

Várias diretivas publicando um controlador com o mesmo nome.

Múltiplas diretivas declaradas com a opção de transclusão.

Várias diretivas tentando definir um modelo ou templateURL.

Tente remover o escopo isolate na myDraggable do myDraggable :

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

Substitua scope.enabled por attrs.enabled :

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

E modifique seu modelo para ligar o atributo enable:

 

DEMO

Um elemento DOM está criando uma colisão com seus escopos isolados tentados. Portanto, você deve sempre se perguntar se um escopo isolado é necessário.

Considere remover o escopo isolado em myDraggable , interpolando o valor myDraggable (como você fez com isDraggable) e acessando o atributo na function de link .

 
I am draggable {{isDraggable}}
 ... replace: false, link: function (scope, elm, attrs) { var startX, startY, initialMouseX, initialMouseY, enabled = attrs.myDraggable === 'true'; if (enabled === true) { ... 

Veja o seu Plunker atualizado aqui e observe a mudança no modelo myPopup.

Se você quiser ver as alterações do atributo myDraggable, implemente algo como:

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

Ver documentos de atributos angulares $ observe a function

meu erro foi semelhante:

Erro: [$ compile: multidir] Múltiplas diretivas [grupos, grupos] solicitando escopo novo / isolado em:

No meu caso eu tinha uma declaração duplicada de

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

no arquivo app.js / app.ts

e ao mesmo tempo no próprio componente

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

A remoção de app.js / app.ts corrigiu o problema.

Eu corri para uma situação semelhante. Se isso não estragar seu layout e você definitivamente precisar ter um escopo isolado em ambas as diretivas, minha sugestão seria remover a propriedade replace: true da definição da diretiva myPopup.

Existe uma maneira de contornar isso.

Você não irá isolar o escopo da diretiva, em vez disso, criaremos um novo escopo isolado usando o método $ new . Este método cria um novo escopo filho, se você usar true no primeiro parâmetro, ele criará um escopo isolado:

Se for true, o escopo não herdará protótipo do escopo pai. O escopo é isolado, pois não pode ver as propriedades do escopo pai>. Ao criar widgets, é útil que o widget não leia acidentalmente o estado pai.

Mas não é um problema porque temos access ao escopo privado pela function de link da diretiva, portanto é possível trabalhar em paralelo com o escopo “pai” e isolado em um comportamento muito próximo de uma diretiva com um escopo isolado.

Veja o exemplo abaixo:

 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. //(...) } 

Eu desenvolvi este trabalho em torno de uma diretiva de validação, que funciona muito bem.

Eu incluí meu arquivo js diretivo duas vezes quando eu comprimi meu aplicativo. Isso causou o erro.

Deixe de fora o escopo: {enabled: ‘= myDraggable’} do seu “myDraggable” -diretivo, você não precisa dele. Assim:

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