Making a search bar work in AlpineJS where the searched items in x-data come from x-init

Basically trying to modify the dynamic search bar that can be found in Alpine docs, but with "items" ("bands" in my case) coming from x-init that fetches a JSON. Outside of this search bar all the desired data from this JSON is displayed so it's not like the JSON itself is empty, but in this particular situation x-text doesn't even list any of the values, as if the JSON data never gets to the x-data/"bands" array.

This is what I currently have, like I said it's a little modification of the search bar from the docs.

<div x-data="{
        search: '', 
        bands: [], 
        get filteredItems() {
            return this.bands.filter(
                i => i.startsWith(this.search)
            )
        }
    }"  x-init="bands = await (await fetch('/bands/')).json()">
    <input x-model="search" placeholder="Search...">
 
        <template x-for="band in filteredItems" :key="band">
            <p x-text="`${band.name}`"></p>
        </template>

</div>

I'd be grateful if anyone told me what exactly this seemingly straightforward chunk of code is missing.

It looks like the code you have provided is missing a few key pieces that are necessary for the search bar to function properly.

First, it appears that you are trying to use the startsWith method on the bands array, but it seems that the bands array is an array of objects, not strings. The startsWith method is only available on strings, so you will need to adjust the filter condition to match the properties of the objects in the bands array.

Second, you are trying to display the name property of each band object, but it is not clear from the code you provided where you are getting the name property from. Make sure that your JSON data contains the 'name' property of the band object.

Lastly, It appears that you are using the x-init directive to fetch the JSON data, but the x-init directive is not used to fetch data. It is used to initialize data and perform any setup that is needed before the component is rendered. Instead, you can use the mounted() lifecycle method to fetch the data, and then store the data in the bands array.

Here's an example of how you could modify your code to make it work:

<div x-data="{
        search: '', 
        bands: []
    }"  x-init="mounted()">
    <input x-model="search" placeholder="Search...">
 
        <template x-for="band in bands" :key="band.id">
            <p x-text="band.name"></p>
        </template>

</div>
<script>
    function mounted() {
        fetch('/bands/')
        .then(response => response.json())
        .then(data => {
            this.bands = data.filter(band => band.name.startsWith(this.search))
        })
    }
</script>

This modification will fetch the JSON data and store it in the bands array, and then use the mounted() lifecycle method to filter the data using the search input and the startsWith method. This will display the name of the band objects that match the search input.

<div x-data="{search: '', bands: [], 
  get filteredItems() {
    return this.bands.filter(i => i.name.toLowerCase().includes(this.search))
    }
  }" x-init="bands = await (await fetch('/bands/')).json()">
      <input x-model="search" placeholder="Search...">
   
          <template x-for="band in filteredItems" :key="band.name">
              <p x-text="band.name"></p>
          </template>
  
  </div>

This answer was posted as an edit to the question [Solved ]Making a search bar work in AlpineJS where the searched items in x-data come from x-init by the OP dirt1992 under CC BY-SA 4.0.

Back to Top