Search code examples
javascriptglobal-variablesalpine.js

Setting an AlpineJS data string in a function from outside of the component without using arrays or objects


How do I get to update a alpine string variable from a function outside of the component ?

<script>     
let global_status = 'IDLE';
const contactServer = (global_status) =>
{
    global_status = "PROCESSING";
}
</script>     
<div x-data="{ status: global_status }">
    <button x-on:click="contactServer(status)">CLICK</button>
    <p>
        Status :
        <span x-text="status"></span>
    </p>
</div>

Because this works if I set it to as as an array.

<script>     
let global_status = ['IDLE'];
const contactServer = (global_status) =>
{
    global_status[0] = "PROCESSING";
}
</script>     
<div x-data="{ status: global_status }">
    <button x-on:click="contactServer(status)">CLICK</button>
    <p>
        Status :
        <span x-text="status[0]"></span>
    </p>
</div>

Solution

  • You need to use an Alpine.js API to mutate a data object, otherwise it will lose its reactivity. For this kind of problem the simplest solution is to use the global Alpine.store() object that is easily accessible externally as well. You can mutate a variable inside a store object directly, or you can define an API inside the store to mutate the data. See the live example below:

    <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
    
    <script>
    const contactServer = () => {
        // Mutate state directly:
        Alpine.store('global_status').status = "PROCESSING...";
        
        // Mutate state using API defined in the store object
        setTimeout(() => {Alpine.store('global_status').idle()}, 1000)
    }
    
    document.addEventListener('alpine:init', () => {
        Alpine.store('global_status', {
            status: 'IDLE',
            processing() {
                this.status = 'PROCESSING'
            },
            idle() {
                this.status = 'IDLE'
            }        
        })
    })
    </script>
    
    <div x-data="{}">
      <button x-on:click="contactServer()">Contact server</button>
      <p>
          Status :
          <span x-text="$store.global_status.status"></span>
      </p>
    </div>