2013-03-21 19 views
13

Tworzę wielokrotnego użytku bit html za pośrednictwem dyrektywy. HTML będzie mieć kilka zmiennych, które chcę przekazać z oryginalnego zakresu. Dokonuje się tego łatwo, deklarując atrybuty na dyrektywie, a następnie tworząc zakres izolowania i przechwytując je. Pytanie brzmi, czy istnieje lepszy sposób na zrobienie tego dla większej liczby zmiennych? Myślałem o przejściu w obiekcie takim jak {firstAttr: $scope.one, secondAttr: $scope.two...} i wybrania tego obiektu oddzielnie, aby uzyskać każdy element. Działa to po raz pierwszy, ale dwukierunkowe wiązanie danych nie działa (nawet przy użyciu znaku "=").Jak przekazać wiele wartości do dyrektywy Angularjs?

Problem polega na tym, że jest to obiekt, a nie każda z poszczególnych części obiektu. Czy mógłbym użyć funkcji kompilacji w dyrektywie, aby dodać każdy z atrybutów do elementu lub coś takiego? tak:

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

byłyby tłumaczone na:

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

tamtędy mój wiązania z danymi będzie działać zgodnie z oczekiwaniami poprzez przechwytywanie atrybuty w dyrektywie. W jaki sposób chciałbym osiągnąć ten projekt, czy jest tylko inny sposób, aby to zrobić?

Odpowiedz

1

Możesz zmienić zakres dyrektywy w następujący sposób

.('mydirective ', function(){ 

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

To zadziała, jeśli zmienię atrybut na inny. Próbuję tego uniknąć. Chcę wysłać wszystkie moje databindings na jednym atrybucie, a następnie rozdzielić je. Może ponownie przeczytaj pytanie, aby wyjaśnić. – Spencer

0

Pytanie brzmi, czy istnieje lepszy sposób to zrobić dla większej liczby zmiennych?

Nie sądzę. Jak już odkryłeś, próba przekazania ich jako jednego obiektu powoduje, że obiekt jest databound, a nie poszczególne części.

Nawet jeśli mógłbyś uzyskać coś, co działałoby z $ compile, nie byłoby oczywiste dla innych osób czytających twój kod, co się dzieje.

Inną opcją jest albo nie tworzyć zakresu (scope: false, który jest domyślnym dla dyrektyw) lub utworzyć nowy zakres dzieckiem (scope: true), ale wymaga, aby zakres wywołanie musi użyć dyrektywy korzystania niektóre nazwy własności zakres . Wtedy nie musisz określać żadnych atrybutów. To sprawia, że ​​stosowanie dyrektywy jest bardziej restrykcyjne, ale uważam, że są to dwie opcje: określ wiele atrybutów lub wymagane są określone nazwy właściwości zakresu.

15

Idea dyrektywy związanej z databindingiem jest interesująca, ale nie jest to sposób, w jaki bym to zrobił, ponieważ uważam, że napotkasz problemy z priorytetami dyrektywy, a także fakt, że jest to bardzo niestandardowe i sprawiłoby, że twój kod byłby trudny do naśladowania. dla przyszłych programistów. Jest na to kilka sposobów, dlatego omówię 3 różne rozwiązania, z których korzystałem.

Rozwiązanie 1

Jeśli trzeba tylko jeden sposób powiązania danych, najprostszym rozwiązaniem jest użycie zakres kątowy jest. $ Eval funkcja na ciąg znaków obiektu wewnątrz swojej dyrektywy po interpolacji żadnych prostych zmiennych zakres języka na używając {{}}. Reprezentacja łańcuchowa nie musi być poprawna JSON, ponieważ zauważysz w poniższym przykładzie, że nie umieszczam cudzysłowów wokół kluczy obiektów.

w widoku:

<div databinding="{one:'first', two:{{scopeVar}}, complex:[1,2, "Hi"]}"></div> 

A w JavaScript:

app.directive('databinding', function() { 
    return{ 
     link: function (scope, elm, attrs) { 

     console.debug(scope.$eval(attrs['databinding'])); 

     } 
    } 
}); 

roztworu 2

Innym rozwiązaniem wiąże jednokierunkowe danych do utworzenia obiektu funkcji Wewnątrz kontroler i przekazać go do dyrektywy za pomocą "@" (lub nawet "="):

W regulatorze:

$scope.options = {one: "first, two: "second"}; 

W widoku:

<div databinding="options"></div> 

A w javascript:

app.directive('databinding', function() { 
    return{ 
     scope: { 

     options: "@" //Can also use = here 

     }, 
     link: function (scope, elm, attrs) { 

     console.log(scope.options); 

     } 
    } 
}); 

Rozwiązanie 3

Jeśli potrzebują dwukierunkowy powiązanie danych, w większości jesteś poza szczęście, ponieważ nie ma eleganckiego sposobu na zrobienie tego. JEDNAKŻE, jeśli jesteś na rynku rozwiązań hackish, możesz osiągnąć dwukierunkowe powiązanie danych z metodą bardzo podobną do rozwiązania 2, ale ze zmianą w obiekcie opcji.

Zamiast zadeklarować obiekt opcji zawierający proste typy danych pierwotnych, takie jak łańcuchy, utwórz obiekt obojętny wewnątrz obiektu opcji, który następnie zadeklarujesz w swoim zmiennym. Robiąc to w ten sposób, zmiany w zmiennych zakresu w kontrolerze będą również realizowane w ramach dyrektywy, co zostało zademonstrowane w ramach limitów czasu.

Kontroler:

$scope.someScopeVar = "Declared in controller"  

$scope.options = { 
    dummy: { 
    one: $scope.someScopeVar, 
    two: "second" 
    } 
} 

window.setTimeout(function(){ 

    $scope.someScopeVar = "Changed in controller"; 

}, 2000) 

Widok:

<div databinding="options"></div> 

dyrektywa:

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) 

     } 
    } 
}); 

Ta metoda działa od obiektów javascript przechodzi przez odniesienie natomiast prymitywy są kopiowane. Poprzez zagnieżdżenie obiektu w obiekcie powiązanie danych zostaje zachowane.

+0

Dokładnie, czego teraz potrzebuję. Dziękuję Ci! – DavidR

+0

@ scottmas can solution 2 be used with 'compile' zamiast' link'? – AKJ

+0

Niestety nie, ponieważ krok kompilacji nie jest obiektem zasięgu. Jedynym sposobem, w jaki mogę uzyskać dostęp do opcji w czasie kompilacji, jest zadeklarowanie obiektu opcjonalnego bezpośrednio w html jako atrybutu, a następnie możesz po prostu JSON.parse go. – Scottmas

Powiązane problemy