Как получить двухстороннюю привязку данных в директиве * без * области выделения?
Использование scope: { ... }
в директиве вводит область выделения, которая не прототипически наследуется от ее родительской области. Но я всегда использовал его по другой причине: удобный способ объявить атрибуты HTML с двусторонней привязкой данных:
scope: {
attr1: '=',
attr2: '?='
}
Чтобы получить неизолированную область видимости, вы должны использовать scope: true
, что не дает возможности объявить такие атрибуты. Теперь мне нужна директива с неизолированной областью, но с двухсторонней привязкой. Какой лучший способ достичь этого?
Пример: Мой пример использования выглядит примерно так: в представлении outer-directive
:
<div ng-repeat="e in element">
<inner-directive two-way-attr="e.value"></inner-directive>
</div>
Но inner-directive
находится в том же модуле, что и outer-directive
. Он не должен быть инкапсулирован с областью изоляции. На самом деле, мне нужно использовать наследование $scope
для других целей, поэтому область выделения не является опцией. Это просто, что использование атрибута HTML для установления этой двусторонней связи чрезвычайно удобно.
Ответы
Ответ 1
Ответ на pixelbits помог мне разобраться в этом много времени, но, будучи прямым ответом на мой первоначальный вопрос, кажется слишком сложным. Изучив это, решение действительно довольно просто.
Возьмите директиву с областью выделения, подобной этой:
scope: { model: '=myModel' },
link: function(scope, element, attr) {
//...
}
Ниже приведен эквивалент, за исключением того, что область не изолирована:
scope: true,
link: function(scope, element, attr) {
scope.model = scope.$parent.$eval(attr.myModel);
//...
}
См. рабочий пример здесь: http://jsfiddle.net/mhelvens/SZ55R/1/
Ответ 2
Рабочий демонстрационный пример здесь
В директиве той же возможно иметь как неизолированную область видимости, так и область выделения. Возможно, вы захотите сделать это, например, если у вас есть сочетание неизолированных шаблонов (что означает, что они не должны искать привязки через наследование сферы) и изолированные шаблоны (они должны искать привязки только в своей области) и они оба определены в одной и той же директиве.
Чтобы настроить область выделения и неизолированную область, вы можете сделать следующее:
- В определении вашей директивы укажите
scope=true
-
В вашей функции ссылок скомпилируйте и привяжите шаблон к параметру области. Когда вы это делаете, привязки оцениваются с помощью неизолированной области (что означает, что она разрешает привязки через наследование прототипа).
link: function(scope, element, attr) {
// this template should look for 'model' using scope inheritance
var template2 = angular.element('<div> Prototypical Scope: {{ model }}</div>');
// add the template to the DOM
element.append(template2);
// compile and link the template against the prototypical scope
$compile(template2)(scope);
}
Преимущество прототипического наследования объектов заключается в том, что вам не нужно явно импортировать привязки в текущую область ваших директив. Пока он определен в текущей области действия или в какой-либо области выше цепочки наследования (вплоть до корневой области), время выполнения angular сможет ее разрешить.
-
В той же функции ссылок определите изолированную область с помощью scope.$new(true)
. Вы можете установить двустороннюю привязку своей модели, импортировав модель в свою изолированную область - isolatedScope.model = scope.$eval(attr.model)
:
link: function(scope, element, attr) {
// this template should look for 'model' in the current isolated scope only
var template = angular.element('<div>Isolate Scope: {{model}}</div>');
// create an isolate scope
var isolatedScope = scope.$new(true);
// import the model from the parent scope into your isolated scope. This establishes the two-way binding.
isolatedScope.model = scope.$eval(attr.model);
// add the template to the DOM
element.append(template);
// compile and link the template against the isolate scope
$compile(template)(isolatedScope);
}
Преимущество области изоляции заключается в том, что любые привязки, которые существуют (т.е. находятся в области видимости), являются теми, которые вы явно импортируете. Контрастируйте это с неизолированной областью - там, где привязки не должны быть явно определены в текущей области действия - она может быть унаследована от любой области действия выше цепочки.
Ответ 3
Я написал это. Вы используете его следующим образом:
twowaybinder.attach($scope, $attrs.isDeactivated, 'isDeactivated');
.factory('twowaybinder', function ($parse) {
function twoWayBind($scope, remote, local){
var remoteSetter = $parse(remote).assign;
var localSetter = $parse(local).assign;
$scope.$parent.$watch(remote, function (value) {
localSetter($scope, value);
});
$scope.$watch(local, function (value) {
remoteSetter($scope, value);
});
}
return {
attach : twoWayBind
};
});
Это даст истинную двустороннюю привязку из значений области. Примечание. Я не считаю, что $scope. $Parent необходим, как в унаследованном или без видимого сценария, какое-либо выражение должно разрешаться в текущей области. Вам нужно будет только вызывать $parent в изолированной области, в этом случае вы не использовали бы это, вы бы использовали изолированную конфигурацию области.
Ответ 4
вы можете использовать две директивы
если gg - объект, то "=" указывает на одно место памяти!
angular.module('mymodule', []).directive('a', function($parse, $modal) {
return {
restrict : 'A',
scope : {
gg : "="
},
require : "b",
link : function(scope, element, attrs, bCtrl) {
scope.$watch('gg',function(gg){
bCtrl.setset(scope.gg);
}
}
}
});
angular.module('mymodule').directive('b', function($parse, $modal) {
return {
restrict : 'A',
/*
* scope : { showWarn : "=" },
*/
controller : function($scope) {
$scope.bb = {};
this.setset = function(nn) {
$scope.bb=nn;
};
}
});