Ustaw zmienną zakresu kątowego w znacznikach

95

Proste pytanie: Jak mogę ustawić wartość zakresu w html, aby mój kontroler mógł go odczytać?

var app = angular.module('app', []);

app.controller('MyController', function($scope) {
  console.log($scope.myVar);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app'>
  <div ng-controller="MyController" app-myVar="test">
    {{myVar}}
  </div>
</div>

JSFiddle: http://jsfiddle.net/ncapito/YdQcX/

Nic
źródło
Lepiej byłoby stworzyć dyrektywę, która to załatwi. Dyrektywa zawierałaby: parametr (y), kontroler specyficzny dla tej dyrektywy i szablon dla znaczników „myMap”.
Ian Mercer
Tak właśnie zrobiłem ... po prostu mam problemy z dostępem do $ scope.myVar w kontrolerze dyrektywy. Dlaczego muszę używać zegarka w kontrolerze, aby uzyskać dostęp do zmiennych zakresu?
Nix
1
Może mógłbyś zamieścić swoją dyrektywę? Spójrz na „Zrozumienie transkluzji i zakresów” tutaj docs.angularjs.org/guide/directive Prawdopodobnie potrzebujesz zakresu: {myVar: '='} i powiesz, my-var="foo"kiedy go wywołasz. Zwróć uwagę na użycie łącznika w porównaniu z camelCase. Uwaga: footutaj jest oceniane , jeśli nie chcesz, aby użycie znaku „@” w definicji zakresu miało dostęp do wartości atrybutu.
Ian Mercer
1
@Nix Czy możesz wyjaśnić, dlaczego wartość musi zostać zainicjowana w widoku, a nie w kontrolerze? Zakładam, że już wiesz, że to nie jest konwencjonalny sposób inicjowania wartości (w przeciwnym razie nie pytałbyś), a inni będą w stanie udzielić ci lepszych odpowiedzi, jeśli lepiej zrozumieją twój przypadek użycia.
Sean the Bean
1
@SeantheBean Byłem młody i głupi ...;) nie mam pojęcia, dlaczego musiałem to zrobić. Prawdopodobnie próbowałem coś zrobić.
Nix

Odpowiedzi:

139

ng-initnie działa, gdy przypisujesz zmienne wewnątrz pętli. Posługiwać się {{myVariable=whatever;""}}

Końcowe "" zatrzymuje obliczanie wyrażenia kątowego na dowolny tekst.

Wtedy możesz po prostu zadzwonić {{myVariable}} aby wyświetlić wartość zmiennej.

Okazało się, że jest to bardzo przydatne podczas iteracji wielu zagnieżdżonych tablic i chciałem zachować moje bieżące informacje o iteracji w jednej zmiennej zamiast wielokrotnego wykonywania zapytań.

Glogo
źródło
1
Chociaż to działa, wydaje się być hackem. Oznacza to, że ogólnie dobrą praktyką jest używanie {{}}tylko do wyświetlania pojedynczej zmiennej, a nie do przypisywania zmiennych. Powiedziałbym, że stackoverflow.com/a/16799763/814160 jest bardziej poprawny (mniej kodu JS w widoku).
Sean the Bean
1
+1 dla @SeantheBean - przetestowałem to. Wydaje się, że występują problemy z kontrolerami podrzędnymi i zakresem przypisywania zmiennej w znaczniku. Dyrektywa działa dla moich celów i wydaje się być solidnym rozwiązaniem.
Paul Carlton,
2
Wydaje się, że to nie działa w angular2 / 4 - Wiązania nie mogą zawierać przypisań
Demodave
1
@Demodave powinieneś zamiast tego ustawić wszystkie zmienne kontrolera w kodzie Typescript i używać szablonu tylko do połączenia Typescript z HTML. Szablon nie powinien przypisywać zmiennych.
boxmein
81

ngInit może pomóc w inicjalizacji zmiennych.

<div ng-app='app'>
    <div ng-controller="MyController" ng-init="myVar='test'">
        {{myVar}}
    </div>
</div>

przykład jsfiddle

Mark Coleman
źródło
3
Należy zauważyć, że nie polecają tego rozwiązania dla prawdziwych aplikacji (ale tak naprawdę nie sugerują alternatywy): docs.angularjs.org/guide/dev_guide.mvc.understanding_model
Mike Robinson
U mnie to zadziałało, jednak początkowo zmienna była nadal niezdefiniowana w kontrolerze. Zrobiłem małą pętlę interwałową: var interwał = setInterval (function () {if ($ scope.cokolwiek) {// dostuff clearInterval (interwał);}}, 10);
roelleor
19

Utwórz dyrektywę o nazwie myVarwith

scope : { myVar: '@' }

i nazwij to tak:

<div name="my_map" my-var="Richmond,VA">

W szczególności należy zwrócić uwagę na odniesienie w dyrektywie do przypadku wielbłąda do nazwy znacznika z łącznikiem.

Aby uzyskać więcej informacji, zobacz „Understanding Transclusion and Scopes” tutaj: - http://docs.angularjs.org/guide/directive

Oto Fiddle, który pokazuje, jak można kopiować wartości z atrybutów do zmiennych zakresu na różne sposoby w ramach dyrektywy.

Ian Mercer
źródło
Chcę móc robić wiele var-nick='my' var-nick2='test'. Chyba że możesz wymyślić sposób na zaimplementowanie go za pomocą dyrektyw, których właśnie zamierzam użyćng-init
Nix
Możesz uwzględnić wiele atrybutów w zakresie, wystarczy, że jeden z nich będzie nazwą dyrektywy, którą chcesz wykonać (lub umieść tę nazwę również w kodzie HTML). scope: {varNick: '@', varNick2: '@'}
Ian Mercer
Ale nie jest skalowalne? Musiałbym zdefiniować dyrektywę dla każdej zmiennej?
Nix
Nie, nie potrzebujesz dyrektywy dla każdej zmiennej. Spójrz na skrzypce, które dodałem do odpowiedzi.
Ian Mercer,
Przepraszam, że tęsknię za przeczytaniem, Twój przykład jest doskonały, moją jedyną zmianą był zakres {'@': '@ "}.
Nix
10

Możesz ustawić wartości z html w ten sposób. Myślę, że nie ma jeszcze bezpośredniego rozwiązania z kątowego.

 <div style="visibility: hidden;">{{activeTitle='home'}}</div>
ibsenv
źródło
7
Niezły hack ... poleciłbym <div style="display: none">jednak.
Roger
3

Możesz użyć, ng-initjak pokazano poniżej

<div class="TotalForm">
  <label>B/W Print Total</label>
  <div ng-init="{{BWCount=(oMachineAccounts|sumByKey:'BWCOUNT')}}">{{BWCount}}</div>
</div>
<div class="TotalForm">
  <label>Color Print Total</label>
  <div ng-init="{{ColorCount=(oMachineAccounts|sumByKey:'COLORCOUNT')}}">{{ColorCount}}</div>
</div>

a następnie użyj zmiennej zakresu lokalnego w innych sekcjach:

<div>Total: BW: {{BWCount}}</div>
<div>Total: COLOR: {{ColorCount}}</div>
Mahesh
źródło
Podoba mi się to podejście; wydaje się mniej hacky. Jedno wyjaśnienie, ng-init nie potrzebuje nawiasów klamrowych.
mklbtz
1
$scope.$watch('myVar', function (newValue, oldValue) {
        if (typeof (newValue) !== 'undefined') {
            $scope.someothervar= newValue;
//or get some data
            getData();
        }


    }, true);

Zmienna inicjalizuje się po kontrolerze, więc musisz ją pilnować, a gdy nie jest zainicjalizowana, użyj jej.

Senad Mulaosmanović
źródło
0

Podoba mi się odpowiedź, ale myślę, że byłoby lepiej, gdybyś utworzył funkcję zasięgu globalnego, która pozwoli ci ustawić potrzebną zmienną zakresu.

Więc w globalController create

$scope.setScopeVariable = function(variable, value){
    $scope[variable] = value;
}

a następnie w swoim pliku html wywołaj to

{{setScopeVariable('myVar', 'whatever')}}

Umożliwi to użycie zmiennej $ scope.myVar w odpowiednim kontrolerze

Lance N. Solomon
źródło
0

Jeśli nie jesteś w pętli, możesz użyć ng-init innego, którego możesz użyć

{{var=foo;""}}

"" pozwala nie wyświetlać twojego var

Yohann JAFFRES
źródło