Reputation: 8451
I'm struggling with a timing issue in which I'm getting an error because the data response from the API I'm fetching is not done before trying to process the data.
Here is my example:
### Template
<div class="container mx-auto" x-data="loadIdentities()">
<template x-for="item in filteredIdentities" :key="item">
<h6 x-text="item.name"></h6>
<em x-text="item.role"></em>
</template>
</div>
### SCRIPT
<script>
function loadIdentities() {
return {
search: "",
myData: "",
get filteredIdentities() {
fetch(`/api_endpoint`)
.then(res => res.json())
.then(data => {
this.myData = data
}
)
var foundIdentities = this.myData.filter((item) => {
return item.name
.toLowerCase()
.includes(this.search.toLowerCase());
});
return foundIdentities
},
};
}
</script>
Uncaught TypeError: this.myForData.filter is not a function
Is there a nice way that I can have the processing of the javascript wait for the API request to complete and the data to populate from the API?
Upvotes: 0
Views: 3115
Reputation: 2086
You can also return an empty array as long as there is no data to display.
Example:
(here I load the Identities once using the init()
method and then filter using the getFilteredIdentities
method)
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<script src="//unpkg.com/alpinejs" defer></script>
<div class="p-5 mx-auto" x-data="loadIdentities()">
<input class="border px-2" placeholder="Filter Identities..." x-model="search"
x-on:change="setFilteredItentities()" />
<p class="text-gray-400" x-show="isLoading">Loading Identities...</p>
<template x-for="item in getFilteredIdentities" :key="item.id">
<div class="mt-2 flex items-center">
<h6 x-text="item.first_name"></h6>
<p class="text-xs text-gray-500 ml-2" x-text="item.email"></p>
</div>
</template>
</div>
<script>
function loadIdentities() {
return {
search: "",
isLoading: false,
allIdentities: [],
init() {
this.isLoading = true
fetch(`https://reqres.in/api/users`)
.then(res => res.json())
.then(data => {
this.allIdentities = data.data
})
this.isLoading = false;
},
getFilteredIdentities() {
if (!this.allIdentities || !this.search) {
return this.allIdentities
}
var result = this.allIdentities.filter((item) => {
return item.first_name
.toLowerCase()
.includes(this.search.toLowerCase());
})
return result
}
}
}
</script>
Upvotes: 1
Reputation: 11
You can use await. Declare the function as async like: async function filteredIdentities (){
const response = await fetch('stuff')
const data = await response.json()
return data.filter((item) =>
return item.name
.toLowerCase()
.includes(this.search.toLowerCase());
});
}
The function return a promise and when It Will resolved you have an array
Upvotes: 0