Ответ 1
Идея директивы привязки данных интересна, но это не так, как я бы это сделал, так как я считаю, что вы столкнулись с директивными приоритетными проблемами, а также тем, что она очень нестандартная и сделает ваш код трудным для выполнения будущих программистов. Есть несколько способов сделать это, поэтому я обсужу 3 разных решения, которые я использовал.
Решение 1
Если вам нужна только одна привязка данных, самым простым решением является использование области angular. $eval для строкового представления объекта внутри вашей директивы после интерполирования любых простых переменных сферы на нем с помощью {{}}. Строковое представление даже не должно быть допустимым JSON, так как вы заметите в примере ниже, я не включаю кавычки вокруг ключей объектов.
В представлении:
<div databinding="{one:'first', two:{{scopeVar}}, complex:[1,2, "Hi"]}"></div>
И в javascript:
app.directive('databinding', function () {
return{
link: function (scope, elm, attrs) {
console.debug(scope.$eval(attrs['databinding']));
}
}
});
Решение 2
Еще одно одностороннее решение привязки данных - создать объект-объект внутри контроллера и передать его в директиву с помощью "@" (или даже "=" ):
В контроллере:
$scope.options = {one: "first, two: "second"};
В представлении:
<div databinding="options"></div>
И в javascript:
app.directive('databinding', function () {
return{
scope: {
options: "@" //Can also use = here
},
link: function (scope, elm, attrs) {
console.log(scope.options);
}
}
});
Решение 3
Если вам нужна двусторонняя привязка данных, вам в основном не повезло, так как нет элегантного способа сделать это. ОДНАКО, если вы находитесь на рынке хакерских решений, вы можете выполнить двустороннюю привязку данных с помощью метода, очень похожего на решение 2, но с изменением объекта option.
Вместо объявления объекта option, содержащего простые примитивные типы данных, такие как строки, создайте фиктивный объект внутри объекта option, который затем объявите переменные внутри. Таким образом, изменения в переменных области в вашем контроллере также будут реализованы внутри директивы, как показано через таймауты.
Контроллер:
$scope.someScopeVar = "Declared in controller"
$scope.options = {
dummy: {
one: $scope.someScopeVar,
two: "second"
}
}
window.setTimeout(function(){
$scope.someScopeVar = "Changed in controller";
}, 2000)
Вид:
<div databinding="options"></div>
Директива
app.directive('databinding', function () {
return{
scope: {
options: "=" //You need to use = with this solution
},
link: function (scope, elm, attrs) {
console.log(scope.options.dummy.one); //Outputs "Declared in controller"
window.setTimeout(function(){
console.log(scope.options.dummy.one) //Outputs "Changed in controller"
}, 5000)
}
}
});
Этот метод работает, поскольку javascript передает объекты по ссылке, тогда как примитивы копируются. При вложении объекта в объект сохраняется привязка данных.