Direttive multiple che richiedono un ambito nuovo / isolato

Ho scritto una direttiva per le windows di dialogo (myPopup) e un’altra per il trascinamento di questa finestra di dialogo (myDraggable), ma ho sempre ricevuto l’errore:

Direttive multiple [myPopup, myDraggable] che richiedono un ambito nuovo / isolato

Ecco un Plunker: http://plnkr.co/edit/kMQ0hK5RnVw5xOBdDq5P?p=preview

Cosa posso fare?

Codice 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); } } }; }]);

Da documenti :

Gli scenari di esempio di più direttive incompatibili applicate allo stesso elemento includono:

Direttive multiple che richiedono un ambito isolato .

Direttive multiple che pubblicano un controller con lo stesso nome.

Direttive multiple dichiarate con l’opzione di esclusione.

Direttive multiple che tentano di definire un modello o un modelloURL.

Prova a rimuovere l’ambito isolato sulla direttiva di myDraggable :

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

Sostituisci scope.enabled con attrs.enabled :

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

E modifica il tuo modello per associare l’attributo enable:

 

DEMO

Un elemento DOM sta creando una collisione con i tuoi ambiti tentativo isolati. Pertanto, è necessario chiedersi sempre se è necessario un ambito isolato.

Prova a rimuovere l’ambito isolato su myDraggable , interpolando il valore myDraggable (come hai fatto con isDraggable) e accedendo all’attributo nella funzione link .

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

Vedi il tuo Plunker aggiornato qui e nota la modifica nel modello myPopup.

Se vuoi vedere le modifiche all’attributo myDraggable, implementa qualcosa come:

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

Vedi la funzione di osservazione $ Documento Attributo Angolare

il mio errore era simile:

Errore: [$ compile: multidir] Direttive multiple [gruppi, gruppi] che richiedono un nuovo / ambito isolato su:

Nel mio caso ho avuto una dichiarazione duplicata di

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

nel file app.js / app.ts

e allo stesso tempo sul componente stesso

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

La rimozione da app.js / app.ts ha risolto il problema.

Mi sono imbattuto in una situazione simile. Se non rovina il tuo layout e hai sicuramente bisogno di avere un ambito isolato su entrambe le direttive, il mio suggerimento sarebbe di rimuovere la proprietà replace: true dalla definizione della direttiva myPopup.

C’è un modo per aggirarlo.

Non isolerai l’ambito della direttiva, al posto di essa, creeremo un nuovo ambito isolato usando $ nuovo metodo . Questo metodo crea un nuovo ambito figlio, se si utilizza true al 1 ° parametro verrà creato un ambito isolato:

Se true, l’ambito non eredita prototipicamente dall’ambito principale. L’ambito è isolato, in quanto non può vedere le proprietà genitore> scope. Quando si creano widget, è utile che il widget non legga accidentalmente lo stato genitore.

Ma non è un problema perché abbiamo accesso all’ambito privato tramite la funzione di collegamento direttiva, quindi è ansible lavorare in parallelo con “genitore” e ambito isolato in un comportamento molto vicino di una direttiva con un ambito isolato.

Se l’esempio qui sotto:

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

Ho sviluppato questo lavoro intorno a una direttiva di validazione, che funziona molto bene.

Ho incluso il mio file js direttivo due volte quando ho compresso la mia app. Questo ha causato l’errore.

Lasciare fuori ambito: {abilitato: ‘= myDraggable’} dal tuo “myDraggable” -direttivo non ne hai bisogno. Così:

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