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);