J'essayais d'obtenir une liste via un appel ajax mais avant qu'elle ne soit résolue, la méthode render()
est appelée et le fragment de modèle dépendant de la promesse était impossible de résoudre et jette undefined.
Question : Comment afficher un chargeur jusqu'à ce que j'obtienne les données de la promesse?
import { LitElement, html } from 'lit-element'; class EmpComponent extends LitElement { constructor() { super(); this.data = this.getEmpData(); } getEmpData() { fetch('../../../emp-data.json') .then( function(response) { if (response.status !== 200) { console.log('Looks like there was a problem. Status Code: ' + response.status); return; } response.json().then(data => data); } ) .catch(function(err) { console.log('Fetch Error :-S', err); }); } render() { <div> ${this.data.map(emp => emp.active ? this.dataTemplate(emp) : '')} </div> } } customElements.define('emp-component', EmpComponent);
Obtention de cette erreur:
3 Réponses :
Vous ne renvoyez rien dans getEmpData ()
donc this.data
est indéfini
, d'où l'erreur.
Gardez dans sachez que si vous ajoutez une instruction return
avant l'appel fetch ()
, this.data
contiendra alors une Promise
. La directive jusqu'à
peut vous aider dans ce cas:
import {until} from 'lit-html/directives/until.js'; // ... render() { return html` <div> ${until( this.data.then(data => data.map(emp => emp.active ? this.dataTemplate(emp) : ''), html`<p>Loading...</p>`, )} </div> `; }
étape 1: créez un fichier js
qui renvoie true
ou false
(par exemple util.js)
static get properties() { return { isLoading: { type: Boolean }, canRender: { type: Boolean } } } constructor() { super(); this.isLoading = true; this.canRender = false; this.data = this.getEmpData(); this.isLoading = false; this.canRender = true; } render() { return html ` ${when(this.isLoading,() => html`<p>Loading...</p>`)} ${when(this.canRender,() => html`<your-component></your-component>`)} ` }
étape 2: importez l'utilitaire dans votre fichier js
import { LitElement, html } from 'lit-element'; import { when } from 'util.js' class EmpComponent extends LitElement { static get properties() { return { isLoading: { type: Boolean }, } } constructor() { super(); this.isLoading = true; }
étape 3: définissez une propriété isLoading
dans static get properties
. Ainsi, lors du chargement initial, nous définissons onload
sur true dans constructor
import { LitElement, html } from 'lit-element'; import { when } from 'util.js'
étape 4: une fois les données récupérées, nous sommes prêts à rendre le DOM. Ensuite, nous pouvons définir isLoading
sur false, puis afficher le DOM en utilisant when
export function when(expression, truVal, falseVal) { if (expression) { return truVal(); } if (falseVal) { return falseVal(); } return undefined; }
Ceci est une solution alternative pour jusqu'à
. vous pouvez obtenir plus de détails sur ce blog blog sabarinath
Je commente les parties où vous devez apporter des modifications. Vous n'avez pas besoin de faire des choses bizarres avec d'autres importations
import { LitElement, html } from 'lit-element'; class EmpComponent extends LitElement { constructor() { super(); // you were returning a promise to an Array type... // this.data = this.getEmpData(); // Correct this.data = []; this.getEmpData(); } // ADD PROPS static get properties() { return { data: {type:Array} }; } getEmpData() { fetch('../../../emp-data.json') .then(()=>(response) { if (response.status !== 200) { console.log('Looks like there was a problem. Status Code: ' + response.status); return; } // SET DATA ON RESOLVE response.json().then(data => this.data = data); } ) .catch(function(err) { console.log('Fetch Error :-S', err); }); } render() { <div> $ { (this.data || []).map(emp => emp.active ? this.dataTemplate(emp) : '') } </div> } } customElements.define('emp-component', EmpComponent);