Mar*_*tin 52 scope angularjs angularjs-directive
我为对话框(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);
}
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
Kha*_* TO 62
来自docs:
应用于同一元素的多个不兼容指令的示例场景包括:
多个指令请求隔离范围.
多个指令以相同的名称发布控制器.
使用transclusion选项声明的多个指令.
尝试定义模板或模板URL的多个指令.
尝试删除myDraggable指令中的隔离范围:
app.directive('myDraggable', ['$document',
function ($document) {
return {
restrict: 'A',
replace: false,
scope: { enabled: '=myDraggable' }, //remove this line
Run Code Online (Sandbox Code Playgroud)
替换scope.enabled为attrs.enabled:
if (attrs.enabled == "true") {
Run Code Online (Sandbox Code Playgroud)
并修改模板以绑定enable属性:
<div my-draggable="draggable" enabled="{{draggable}}"
Run Code Online (Sandbox Code Playgroud)
Ste*_*ker 22
DOM元素正在与您尝试的隔离范围创建冲突.因此,您应该始终问自己是否需要隔离范围.
考虑删除隔离范围myDraggable,插入myDraggable值(就像使用isDraggable一样),并访问link函数中的属性.
<div class="draggable" my-draggable="{{isDraggable}}">I am draggable {{isDraggable}}</div>
Run Code Online (Sandbox Code Playgroud)
...
replace: false,
link: function (scope, elm, attrs) {
var startX, startY, initialMouseX, initialMouseY,
enabled = attrs.myDraggable === 'true';
if (enabled === true) {
...
Run Code Online (Sandbox Code Playgroud)
请在此处查看更新后的Plunker ,并注意myPopup模板中的更改.
如果要查看myDraggable属性更改,请执行以下操作:
attrs.$observe('myDraggable', function(iVal) {
enabled = iVal === 'true';
// AND/OR
if (iVal === 'true') doSomething();
});
Run Code Online (Sandbox Code Playgroud)
请参阅Angular Attribute Docs $ observe函数
小智 7
我的错误类似:
错误:[$ compile:multidir]多个指令[groups,groups]要求新的/隔离范围:
在我的情况下,我有重复的声明
.component('groups', new GroupsComponent());
Run Code Online (Sandbox Code Playgroud)
在app.js/app.ts文件中
同时在组件本身上
const groups = angular.module('groups', ['toaster'])
.component('groups', new GroupsComponent());
Run Code Online (Sandbox Code Playgroud)
从app.js/app.ts中删除它修复了问题.
有一种方法可以解决它。
您不会隔离指令的作用域,而是使用$new method创建一个新的隔离作用域。此方法创建一个新的子作用域,如果您在第一个参数中使用 true,它将创建一个隔离的作用域:
如果为 true,则该范围不会原型继承自父范围。范围是隔离的,因为它看不到父 > 范围属性。创建小部件时,小部件不会意外读取父状态很有用。
但这不是问题,因为我们可以通过指令链接函数访问私有范围,因此可以与“父”和隔离范围并行工作,成为具有隔离范围的指令的非常接近的行为。
请看下面的例子:
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.
//(...)
}
Run Code Online (Sandbox Code Playgroud)
我围绕验证指令开发了这项工作,效果很好。