2013-03-21 2 views
13

Я создаю многоразовый бит html через директиву. В html будет несколько переменных, которые я хочу передать из исходной области. Это делается легко, объявляя атрибуты в директиве, затем создавая область изоляции и захватывая их. Вопрос в том, есть ли лучший способ сделать это для большего числа переменных? Я подумал о том, чтобы пройти через объект, например {firstAttr: $scope.one, secondAttr: $scope.two...}, и выбрать этот предмет отдельно, чтобы получить каждую деталь. Это работает в первый раз, но двухсторонняя привязка данных не работает (даже используя «=»).Как передать многие значения в директиву Angularjs?

Проблема связана с объектом, а не с каждой отдельной частью объекта. Могу ли я использовать функцию компиляции в директиве, чтобы добавить каждый из атрибутов к элементу или что-то еще? так:

<mydirective databinding="{one:'first one', two:'second one'}"> 

будет переведен на:

<mydirective one="first one" two="second one"> 

Таким образом, мой привязки будет работать, как и ожидалось, захватив атрибуты в директиве. Как мне пойти на выполнение этого проекта, или есть ли еще один способ полностью сделать это?

ответ

1

Вы можете изменить масштаб в директиве следующий

.('mydirective ', function(){ 

    var linker = function(scope, element){ 
     console.log(scope.one, scope.two);  
    }  
    return { 
     link: linker, 
     scope: {one:"=", two:"="} 
    }  
}); 
+0

Это будет работать, если бы каждая переменная имела другой атрибут. Я пытаюсь избежать этого. Я хочу отправить все свои данные по одному атрибуту, а затем разделить их. Возможно, перечитайте вопрос, чтобы уточнить. – Spencer

0

Вопрос заключается в том, есть ли лучший способ сделать это для большего числа переменных?

Я так не считаю. Как вы уже выяснили, попытка передать их как один объект приводит к тому, что объект представляет собой привязку данных, а не отдельные части.

Даже если вы можете получить что-то, работающее с компиляцией $, для других людей, которые читают ваш код, не будет очевидно, что происходит.

Другой вариант заключается в том, чтобы не создавать область действия (scope: false, которая является директивой по умолчанию), или создать новую область с правами пользователя (scope: true), но требуют, чтобы область вызова должна использовать определенные имена свойств области, чтобы использовать директиву , Тогда вам не нужно указывать какие-либо атрибуты. Это делает использование директивы гораздо более ограничительным, но я думаю, что это ваш выбор: указать несколько атрибутов или потребовать определенные имена свойств области.

15

Идея директивы привязки данных интересна, но это не так, как я бы это сделал, так как я считаю, что вы столкнулись с директивными приоритетными проблемами, а также тем фактом, что она очень нестандартная и сделает ваш код трудным для выполнения для будущих программистов. Есть несколько способов сделать это, поэтому я обсужу 3 разных решения, которые я использовал.

Решение 1

Если вам нужна только один способ связывания данных, самое простое решением является использование сферы угловой х. $ 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'])); 

     } 
    } 
}); 

Solution 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); 

     } 
    } 
}); 

Solution 3

Если вам нужны два пути привязка данных, вам в основном не повезло, так как нет элегантного способа сделать это. ОДНАКО, если вы находитесь на рынке хакерских решений, вы можете выполнить двустороннюю привязку данных с помощью метода, очень похожего на решение 2, но с изменением объекта 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) 

     } 
    } 
}); 

Этот метод работает с Java-объекты, проходит по ссылке, тогда как примитивы копируются. При вложении объекта в объект сохраняется привязка данных.

+0

Точно, что мне нужно сейчас. Спасибо! – DavidR

+0

@scottmas can solution 2 можно использовать с 'compile' вместо' link'? – AKJ

+0

К сожалению нет, поскольку шаг компиляции не является объектом области. Единственный способ, с помощью которого я могу получить доступ к параметрам во время компиляции, - это объявление объекта опции непосредственно в html как атрибут, а затем вы можете просто JSON.parse. – Scottmas

Смежные вопросы