ejemplos - directivas personalizadas angularjs
MĂșltiples directivas[myPopup, myDraggable] solicitando alcance nuevo/aislado (7)
De los docs :
Ejemplos de escenarios de múltiples directivas incompatibles aplicadas al mismo elemento incluyen:
Múltiples directivas solicitando alcance aislado .
Múltiples directivas publicando un controlador bajo el mismo nombre.
Múltiples directivas declaradas con la opción de transclusión.
Múltiples directivas que intentan definir una plantilla o templateURL.
Intente eliminar el ámbito de aislamiento en la directiva de myDraggable
:
app.directive(''myDraggable'', [''$document'',
function ($document) {
return {
restrict: ''A'',
replace: false,
scope: { enabled: ''=myDraggable'' }, //remove this line
Reemplace scope.enabled
con attrs.enabled
:
if (attrs.enabled == "true") {
Y modifique su plantilla para enlazar el atributo de habilitación:
<div my-draggable="draggable" enabled="{{draggable}}"
Escribí una directiva para diálogos (myPopup) y otra para arrastrar este diálogo (myDraggable), pero siempre obtengo el error:
Múltiples directivas [myPopup, myDraggable] solicitando alcance nuevo / aislado
Aquí hay un Plunker: http://plnkr.co/edit/kMQ0hK5RnVw5xOBdDq5P?p=preview
¿Que puedo hacer?
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: ''<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);
}
}
};
}]);
Deje fuera el alcance: {enabled: ''= myDraggable''} de su directivo "myDraggable" no lo necesita. Asi que:
return {
restrict: ''A'',
replace: false,
link: function (scope, elm, attrs) {
He incluido mi archivo js de directivas dos veces cuando comprimí mi aplicación. Esto causó el error.
Me encontré con una situación similar. Si no arruina su diseño y definitivamente necesita tener un alcance aislado en ambas directivas, mi sugerencia sería eliminar la propiedad replace: true
de la definición de la directiva myPopup.
Un elemento DOM está creando una colisión con sus intentos de aislar ámbitos. Por lo tanto, siempre debe preguntarse si se necesita un alcance aislado.
Considere eliminar el ámbito de aislamiento en myDraggable
, interpolar el valor de myDraggable (como hizo con isDraggable) y acceder al atributo en la función de 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) {
...
Vea su Plunker actualizado here y observe el cambio en la plantilla myPopup.
Si desea ver los cambios del atributo myDraggable, implemente algo como:
attrs.$observe(''myDraggable'', function(iVal) {
enabled = iVal === ''true'';
// AND/OR
if (iVal === ''true'') doSomething();
});
Ver en función de los documentos de atributo angular $ observar
mi error fue similar:
Error: [$ compile: multidir] Directivas múltiples [grupos, grupos] que solicitan un alcance nuevo / aislado en:
En mi caso tuve duplicada declaración de
.component(''groups'', new GroupsComponent());
en el archivo app.js / app.ts
y al mismo tiempo en el propio componente
const groups = angular.module(''groups'', [''toaster''])
.component(''groups'', new GroupsComponent());
Al eliminarlo de app.js / app.ts se solucionó el problema.
Hay una manera de evitarlo.
No aislará el alcance de la directiva, en lugar de ello, crearemos un nuevo alcance aislado usando el método $ new . Este método crea un nuevo alcance secundario, si usa true en el primer parámetro, creará un alcance aislado:
Si es verdadero, entonces el alcance no se hereda de forma prototípica del alcance principal. El ámbito está aislado, ya que no puede ver las propiedades de ámbito> padre. Al crear widgets, es útil que el widget no lea accidentalmente el estado principal.
Pero no es un problema porque tenemos acceso al ámbito privado mediante la función de enlace de la directiva, por lo que es posible trabajar en paralelo con el alcance "primario" y aislado en un comportamiento muy cercano de una directiva con un alcance aislado.
Vea el siguiente ejemplo:
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); //parent -> isolatedscope
};
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.
//(...)
}
Desarrollé este trabajo en torno a una directiva de validación, eso funciona muy bien.