0

ich eine Winkelkomponente und Controller haben, der diese wie folgt aussehen:ngShow Ausdruck zu früh ausgewertet

export class MyController{ 

    static $inject = [MyService.serviceId]; 

    public elements: Array<string>; 
    public errorReceived : boolean; 

    private elementsService: MyService; 

    constructor(private $elementsService: MyService) { 
     this.errorReceived = false; 
     this.elementsService= $elementsService; 
    } 

    public $onInit =() => { 
     this.elements = this.getElements(); 
     console.log("tiles: " + this.elements); 
    } 


    private getElements(): Array<string> { 
     let result: Array<string> = []; 
     this.elementsService.getElements().then((response) => { 
      result = response.data; 
      console.log(result); 
     }).catch(() => { 
      this.errorReceived = true; 
     }); 
     console.log(result); 
     return result; 
    } 
} 

export class MyComponent implements ng.IComponentOptions { 
    static componentId = 'myId'; 

    controller = MyController; 
    controllerAs = 'vm'; 

    templateUrl = $partial => $partial.getPath('site.html'); 
} 

MyService Umsetzung wie folgt aussieht:

export class MyService { 

    static serviceId = 'myService'; 

    private http: ng.IHttpService; 

    constructor(private $http: ng.IHttpService) { 
     this.http = $http; 
    } 

    public getElements(): ng.IPromise<{}> { 
     return this.http.get('./rest/elements'); 
    } 

} 

Das Problem, das ich Gesicht ist, dass das Array elements enthält nach dem Aufruf von onInit() ein leeres Array. Später sehe ich jedoch, dass Daten empfangen wurden, da die Erfolgsfunktion in getELements() aufgerufen wurde und die Elemente in die Konsole geschrieben wurden.

Elemente, die ich in meiner Vorlage verwendet, um zu entscheiden, ob ein bestimmtes Element angezeigt werden soll:

<div> 
    <elements ng-show="vm.elements.indexOf('A') != -1"></elements> 
</div> 

Das Problem ist jetzt, dass vm.elements zunächst ein leeres Array enthält, und erst später wird das Array gefüllt mit der tatsächliche Wert. Aber dann wurde dieser Ausdruck in der Vorlage bereits ausgewertet. Wie kann ich das ändern?

+0

Möchten Sie eine Änderungserkennung erzwingen, nachdem die Werte geändert wurden, können Sie Observables auch verwenden, um die Änderungserkennung automatisch zu aktivieren, nachdem eine Variable den Wert im tempaptate ändert –

+0

In Ihrem Controller ist 'getElements() 'falsch. Die Implementierung macht überhaupt keinen Sinn –

+1

Es gibt keine "Angular 1.5". Es gibt nur AngularJS 1.5. Machen wir ein verwirrendes Szenario nicht mehr mit faulen Namen. – isherwood

Antwort

0

Ihre aktuelle Implementierung macht keinen Sinn. Sie müssen verstehen, wie Versprechen und asynchrone Konstrukte in dieser Sprache funktionieren, um Ihr Ziel zu erreichen. Zum Glück ist das nicht zu schwer.

Das Problem mit Ihrer aktuellen Implementierung ist, dass Ihre init-Methode sofort ein leeres Array zurückgibt. Das Ergebnis des Serviceaufrufs wird nicht zurückgegeben, sodass die Eigenschaft in Ihrem Controller einfach wieder an ein leeres Array gebunden wird, das nicht Ihren Vorstellungen entspricht.

sich das folgende statt:

export class MyController { 
    elements: string[] = []; 

    $onInit =() => { 
    this.getElements() 
     .then(elements => { 
     this.elements = elements; 
     }); 
    }; 

    getElements() { 
    return this.elementsService 
     .getElements() 
     .then(response => response.data) 
     .catch(() => { 
     this.errorReceived = true; 
     }); 
    } 
} 

Sie können diese async/await

export class MyController { 
    elements: string[] = []; 

    $onInit = async() => { 
    this.elements = await this.getElements(); 
    }; 

    async getElements() { 
    try { 
     const {data} = await this.elementsService.getElements(); 
     return data; 
    } 
    catch { 
     this.errorReceived = true; 
    } 
    } 
} 

Hinweis durch den Einsatz von mehr lesbar machen, wie die oben die Verwendung von Standard try/catch Syntax ermöglicht. Dies ist einer der vielen Vorteile von async/await.

Noch eine erwähnenswerte Sache ist, dass Ihre Datendienste die Antwort, die data-Eigenschaft auspacken und das zurückgeben sollten, damit sich Ihr Controller nicht mit der Semantik des HTTP-Dienstes beschäftigt.