Template dynamique décoré

Voici une nouvelle façon d'obtenir des templates dynamique selon une logique relativement complexe, mais avec une implémentation bien plus simple. Côté viewModel, il n'y aura qu'à appliquer un décorateur de la façon suivante :

// my-view.js
import {dynamicView} from 'my-decorators/dynamic-view';

@dynamicView
export class MyView {}  

Votre fonction de décoration dynamicView sera capable de charger en XHR ou de la façon que vous voulez un template et de faire un fallback sur le module (comportement normal). Voici l'implémentation du décorateur :

// my-decorators/dynamic-view.js
import {InlineViewStrategy} from 'aurelia-framework';  
import {HttpClient} from 'aurelia-fetch-client';  
import environment from 'environment';  
import {Origin} from 'aurelia-framework';

export function dynamicView(Target) {  
  class NewTarget extends Target {
    constructor(...args) {
      super(...args);
      this.httpClient = args[args.length - 1];
    }

    async activate(...args) {
      await super.activate(...args);
      this.template = `${Origin.get(this.constructor).moduleId}.html`;
      const file = (host => {
        const customHome = host.match(/^(.*)\.my-host/);
        if (customHome && customHome[1] !== 'www') {
          return `${customHome[1]}/${this.template}`;
        }
      })(window.location.hostname);

      if (file) {
        const resp = await http.fetch(`/custom/${file}`);
        if (resp.ok) {
          this._inlineTemplate = true;
          this.template = await resp.text();
        }
      }
    }

    getViewStrategy() {
      // Custom home template from db
      if (this._inlineTemplate) {
        return new InlineViewStrategy(this.template);
      }

      // Standard template
      return this.template;
    }
  }
  NewTarget.inject.push(HttpClient);
  return NewTarget;
}

Dans cet exemple, on veut charger des templates différents si on est sur un sous domaine différent du principal. La fonction getTemplate va donc charger le template en XHR et le stocker dans une propriété de la classe. Ce traitement doit être fait dans le activate car il permet de faire un traitement asynchrone en retournant une promesse (via l'usage de async/await ici). La méthode getViewStrategy est synchrone et est appelée après la résolution de activate. Elle retournera soit un string indiquant le nom du module correspondant au template à charger (comportement normal) soit une instance de InlineViewStrategy (comportement qu'on retrouve avec le décorateur inlineView).
On notera l'usage de Origin.get qui permet de récupérer les métadonnées de la classe, notamment le nom du module permettant de déduire le chemin du template.

Hadrien Lanneau

Développeur de guichet, expert ESNext pile complète

Toulouse, France https://hadrien.eu

Subscribe to Aurelia Framework pour les frenchies

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!