Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

roncallyt's avatar

Alpine.js select with dynamic data

Hi!

The need

I have a bunch of nested selects that has to load data dynamically based on previous selected.

The try

I tried solve this using Alpine.js wrapping all the selects with an alpine component, but since they are wrapped by another component (Input Group), i don't have access to $refs from them.

<div x-data="{
    init() {
        console.log(this.$refs.select);  // Output: undefined
    }
}">                                      // Parent Component
    <div x-data>                         // Input Group
        <select x-ref="select"></select> // Select 1
    </div>
    <div x-data>                         // Input Group
        <select x-ref="select"></select> // Select 2
    </div>
    <div x-data>                         // Input Group
        <select x-ref="select"></select> // Select 3
    </div>
</div>
0 likes
3 replies
martinbean's avatar
Level 80

@roncallyt The x-data directive is for defining components. You just have components within components in your example and not doing anything with them.

If you want to do stuff based on select value changing then listen for the change and do something in response o it:

<div x-data="{
    foo: null,
    bar: null,
    qux: null,
    fooOptions: {},
    barOptions: {},
    quxOptions: {},
    onFooChange(event) {
        // Get and set options for bar select
    },
    onBarChange(event) {
        // Get and set options for qux select
    },
    onQuxChange(event) {
        // Do something when qux select value changes
    }
}">
    <div>
        <select name="foo" x-model="foo" x-on:change="onFooChange">
            <template x-for="(label, value) in fooOptions">
                <option x-bind:value="value">{{ label }}</option>
            </template>
        </select>
    </div>
    <div>
        <select name="bar" x-model="bar" x-on:change="onBarChange">
            <template x-for="(label, value) in barOptions">
                <option x-bind:value="value">{{ label }}</option>
            </template>
        </select>
    </div>
    <div>
        <select name="qux" x-model="qux" x-on:change="onQuxChange">
            <template x-for="(label, value) in quxOptions">
                <option x-bind:value="value">{{ label }}</option>
            </template>
        </select>
    </div>
</div>

When a select value changes, you can do an AJAX request or something to get the options for the next select:

onFooChange(event) {
    var selectedValue = event.target.value;

    // Reset bar options
    this.barOptions = {};

    // Perform AJAX request with Axios
    // Set bar options from Axios response
    axios.get('/some-uri').then(function (response) {
        // For each item in the response, create a new select option
        response.data.data.forEach(function (item) {
            this.barOptions[bar.id] = bar.name; 
        });
    });
},
2 likes

Please or to participate in this conversation.