2016-11-23 1 views
2

Ich versuche eine class zu dem html Element hinzuzufügen, wenn Aurelia zu einer neuen Route navigiert, so dass ich die Seite anders stylen kann, wenn es geladen wird.Detect change to router.isNavigating

Meine aktuelle Lösung ist, die Klasse zu dem main Element hinzuzufügen, weil das ein Teil meiner Ansicht ist und so ist es „einfach funktioniert“, wie folgt aus:

import {inject} from 'aurelia-framework'; 
import {Router} from 'aurelia-router'; 

@inject(Router) 
export class App { 
    constructor (router) { 
     this.router = router; 
    } 
} 

Und dann in meiner Ansicht, die ich einfach tun:

<main class="${router.isNavigating ? 'loading' : ''}"> 
    <router-view></router-view> 
</main> 

Aber, wie ich schon erwähnt, würde ich es vorziehen, die loading Klasse das html Element anstelle hinzuzufügen (so dass ich jeden einzelnen decendant auf der Seite Stil kann). Da das html Element ist nicht Teil meiner Ansicht kann ich dies nicht auf die gleiche Weise erreichen, aber stattdessen muss ich document.documentElement.classList.add('loading') wann immer router.isNavigating ist wahr.

Also meine Frage ist; Wie kann ich das erreichen? Ich weiß, Aurelia unterstützt propertyChanged Methoden, aber ich bin mir nicht sicher, wie es funktioniert, wenn es eine verschachtelte Eigenschaft wie router.isNavigating, routerIsNavigatingChanged() nicht funktioniert. Ich habe auch @computedFrom(router) und Varianten davon versucht, aber kann es nicht zum Funktionieren bringen.

Antwort

2

Ok, also endete ich mit dem EventAggregator stattdessen lösen;

this.ea.subscribe('router:navigation:processing', event => { 
    document.documentElement.classList.add('loading'); 
}); 

this.ea.subscribe('router:navigation:success', event => { 
    document.documentElement.classList.remove('loading'); 
}); 

Ich bin mir nicht sicher, es ist die beste Lösung, aber es scheint zu funktionieren. Würde immer noch gerne wissen, ob es möglich ist, @computedFrom('router.isNavigating') zu tun, weil das versucht, Fehler zu werfen.

+1

Fabios Antwort oben ist das Äquivalent zu '@computedFrom ('router.isNavigating')', aber ich denke, dass die Lösung mit dem EventAggregator der richtige Weg ist, dies zu tun. –

+0

Ich stimme mit @AshleyGrant überein. –

+0

Jungs lassen Sie mich fragen .. using 'isNavigating' zum Anzeigen/Verbergen der Spinner unter der Annahme, ich habe eine API-Aufruf in angehängten Ereignis .. der Spinner wird ausblenden, auch wenn mein Anruf noch nicht beendet wurde? –

4

Eine andere Lösung könnte die BindingEngine sein, aber ich denke, dass EventAggregator eine bessere Lösung ist. Ich poste dies hier nur für Ihre Neugier.

import {BindingEngine} from 'aurelia-binding'; 

export class App { 

    static inject = [BindingEngine]; 

    constructor(bindingEngine) { 
    this.bindingEngine = bindingEngine; 
    } 

    configureRouter(config, router) { 
     //... 
     this.router = router;   
    } 

    attached() { 
    this.navigationSubs = this.bindingEngine 
     .propertyObserver(this.router, 'isNavigating') 
     .subscribe(this.isNavigationChanged); 
    } 

    detached() { 
    this.navigationSubs.dispose(); 
    } 

    isNavigationChanged(newValue, oldValue) { 
    if (newValue) { 
     document.documentElement.classList.add('loading'); 
    } else { 
     document.documentElement.classList.remove('loading'); 
    } 
    } 

} 

Außerdem bin ich nicht sicher, ob class der html Einstellung ist eine gute Idee.

+0

Danke dafür, es ist gut für zukünftige Referenz. Aber wenn Sie beide denken, dass der EA der richtige Weg ist, schätze ich, dass ich mir die Antwort geben werde. – powerbuoy

+1

@powerbuoy Natürlich! Gib dir die Antwort! –

+0

Ich habe Ihren Kommentar zum Hinzufügen einer HTML-Klasse verpasst. Ich liebe das, wenn es um den globalen Stil geht. Wie wenn ein Popup geöffnet ist oder die Seite geladen wird oder was auch immer. Das Setzen einer Klasse auf '' ermöglicht es mir, nicht nur jedes einzelne Kind mit dem Root-Element zu stylen. Wenn es um 'html.loading' geht, zeige ich nur einen Spinner an. Das Hinzufügen der Klasse zum tatsächlichen Spinner würde stattdessen meine Styling-Optionen einschränken und meine app.js eng mit meinem Spinner-HTML verknüpfen, so dass ich definitiv den Ansatz "html.loading" bevorzuge. – powerbuoy