2016-07-26 10 views
36

Piszę prosty komponent kątowy. Podaję parametr jako wiązanie i wyświetlam jego wartość na ekranie. Wszystko działa dobrze: widzę parametr wyświetlany na ekranie.Kątowe komponenty: wiązania są niezdefiniowane w kontrolerze

Składnik:

var app = angular.module("test", []); 
app.component("test", { 
    bindings: { 
    "contactId": "<" 
    }, 
    controllerAs: "model", 
    controller:() => { 
    //output: 'contact id from controller: undefined' 
    console.log(`contact id from controller: ${this.contactId}`); 
    }, 
    template: "<div>Contact id from view: {{model.contactId}}</div>" 
}); 

HTML:

<test contact-id="8"></test> 

Jednak przy próbie dostępu do wiązania z poziomu sterownika (patrz console.log), wartość wiążąca jest undefined. Nie rozumiem, jak może on być dostępny w widoku, ale nie w kontrolerze.

Co robię źle?

Oto plnkr ilustrujący problem.

+1

Brakuje mi coś prostego. Dlaczego "contactId" jest zdefiniowane w cudzysłowach? – Winnemucca

Odpowiedz

33

Podczas korzystania z komponentów kątowych istnieje punkt, w którym sterownik nie został podłączony za pomocą wewnętrznego połączenia łączącego. Jeśli próbujesz to zrobić w konstruktorze swojego kontrolera, nie jesteś połączony z powiązaniami. Interfejs API udostępnia kilka haseł cyklu życia, które możesz zdefiniować, które będą uruchamiane w określonych momentach. Szukasz haka $onInit.

$ onInit() - Powołani na każdym kontrolerze po wszystkie kontrolery na elemencie zostały skonstruowane i mieli powiązania zainicjowana (i przed pre & pocztowych łączenie funkcji dla dyrektyw dotyczących tego elementu). To jest dobre miejsce na umieszczenie kodu inicjalizacyjnego dla kontrolera.

za docs - https://docs.angularjs.org/guide/component

+1

Myślę, że masz rację, należy użyć '$ onInit'. Działa to dla mnie: ' var vm = this; vm. $ OnInit = function() { console.log ("załadowany na init"); console.log ("vm", vm.YOUR_BINDING); console.log ("def yes?", Angular.isDefined (vm.YOUR_BINDINGj)); }; ' – escapedcat

+2

W niektórych scenariuszach twoje powiązania mogą być aktualizowane później, a jego wartości nie są gotowe, gdy nastąpi wywołanie' $ onInit'. W takich przypadkach powinieneś użyć '$ onChanges' i pominąć pierwsze zmiany. Przykład roboczy: https://jsfiddle.net/auxcoder/4hq5gaq0/ – aUXcoder

+1

@aUXcoder To był mój problem. Próbowałem utworzyć komponent zanim dane do połączenia z komponentem były gotowe. Dodanie dyrektywy 'ng-if' w celu upewnienia się, że mam dane przed zainicjowaniem komponentu (np.' ') naprawił problem. – Xchai

4

Słowo kluczowe ten nie wydaje się prace z funkcją strzałki, to działa z

controller: function() { 
    alert('contact id from controller: ' + this.contactId); 
} 

Podczas używania funkcji strzałki ten, wydaje się odnoszą się do obiektu okna, ponieważ

Funkcja strzałka nie tworzy swój własny tym kontekście raczej oddaje tę wartość kontekście otaczającej

6

Wartość contactId jest dostępny na $scope w kontrolerze:

var app = angular.module("test", []); 
app.component("test", { 
    bindings: { 
    "contactId": "<" 
    }, 
    controllerAs: "model", 
    controller: ($scope) => { 
    var model = $scope.model; 
    alert(`contact id from controller: ${model.contactId}`); 
    }, 
    template: "<div>Contact id from view: {{model.contactId}}</div>" 
}); 

link do innej wersji twojego Plunkera here.

+1

dlaczego nie możemy użyć tego słowa kluczowego, gdy używamy stylu funkcji strzałki? –

+0

Możesz użyć 'this' ze stylem funkcji arrow, ale myślę, że w tej sytuacji' this.contactId' nie jest jeszcze dostępny, z powodów wymienionych przez @jusopi. Jeśli masz metody API, takie jak someController.prototype.someMethod, "this" powinno mieć to, czego oczekujesz. Jak wspomniano @jusopi, kolejność wykonywania nie zapełni 'tego' w konstruktorze (nie-prototypowym) zgodnie z oczekiwaniami. – JohnnyCoder

+1

Próbowałem z limitem czasu i nie działa. Jak wspomniałem powyżej, funkcja strzałki nie tworzy własnego kontekstu, raczej przechwytuje tę wartość otaczającego kontekstu. Tak więc w przypadku funkcji strzałki odnosi się to do obiektu okna, a nie kontrolera. –

13

Upewnij się, że używasz łączników dla powiązań w HTML i camelCase dla powiązań w JavaScript.

app.component("test", { 
    bindings: { 
    "myContactId": "<" 
    } 
} 

<test my-contact-id="8"></test> 

Zawsze o tym zapominam.

1

Its może jej nie najlepsze praktyki, ale masz dostęp do tych easyer wartości:

$scope.$ctrl.contactId 

można uzyskać wszystkie powiązania w obiekcie $ ctrl wewnątrz zakresu $.

Mam nadzieję, że jego pomoc

3

będę sugerować pewne zmiany, które naprawdę potrzebują, aby uniknąć tych niezwykłych błędów.

app.component("test", { 
    bindings: { 
    "myContactId": "<" 
    }, 
    controller:function(){ 
    var self=this; 
    this.$onInit=function(){ 
    // do all your initializations here. 
    // create a local scope object for this component only. always update that scope with bindings. and use that in views also. 

     self.myScopeObject=self.myContactId 
    } 
    }, 
    template:'<p>{{$ctrl.myScopeObject}}</p>' 
} 

<test my-contact-id="8"></test> 

kilka punktów:

  1. przechodzące powiązania z komponentem w HTML jest zawsze będzie mój kebab powlekanego ex-contact-id i jego odpowiednia zmienna javascript będzie cammal obudowane: myContactId.

  2. jeśli podajesz wartość insted obiektu, użyj "@" w powiązaniach. jeśli używasz obiektu i przekazujesz obiekt do bindigs, użyj "<. jeśli chcesz 2-drożny wiążące do tego zastosowania obiektu '=' w oprawach config

bindings:{ 
     value:'@', 
     object:'<', // also known as one-way 
     twoWay:'=' 
    } 
Powiązane problemy