Home > Software design >  Access Alpine.js x-data function from within an event
Access Alpine.js x-data function from within an event

Time:06-21

Currently I am trying to modify a common variable between two blocks of data in Alpine.js, but trying to keep both blocks as independent as possible. One block will be executed after the first one is finished. The way I am doing this is by adding an event to inform the second block it is ready for processing, and I hide both blocks according to a variable.

<div x-show="!$store.isSecondBlock" x-data="myFirstData()">
</div>
<div id="secondBlock" x-show="!$store.isSecondBlock" x-data="mySecondData()">
</div>

Where myFirstData() and mySecondData() are defined in another file as:

window.myFirstData = function(){
    return {
        next(){
            //Modifies this.$store.sharedData
            document.getElementById("secondBlock").dispatchEvent(new CustomEvent('secondBlockReady'));
            this.$store.isSecondBlock = true;
        },
    }
}

window.mySecondData = function(){
    return {
        next2(){
            //Some stuff here
        },
        init(){
            document.getElementById("secondBlock").addEventListener('secondBlockReady', function(e){
                this.next2();
            });
        },
    }
}

And the store is created as:

document.addEventListener('alpine:init', () => {
    Alpine.store('isSecondBlock', False);
    Alpine.store('sharedData', [an array here]);
}

The problem is that I can't seem to execute the function next2() in the event listener Uncaught TypeError: this.next2 is not a function at HTMLDivElement.<anonymous>. I check and I can't even access this.$store.sharedData variable from there.

So I get to the point where the event listener is executed when the next() function in myFirstData() is executed , but the next2() is never called because can't be accessed.

It is important that next2() function of mySecondData is run after next() is run in myFirstData. And also important to make sure the mySecondData can run with other blocks of data that don't need to be myFirstData, and only be triggered when the event is executed. One way to imagine it is as a pipeline where each step modifies a shared object and the next step is only executed when the first one finishes.

Is there any approach I can take to accomplish this?

CodePudding user response:

grab a reference to the mySecondData function within the init and use that reference inside the Event Listener so that the Listener function knows how to reference next2()

    window.mySecondData = function(){
    return {
        next2(){
            alert('hi');
        },
        init(){
            self = this;
            document.getElementById("secondBlock").addEventListener('secondBlockReady', function(e){
                self.next2();
            });
        },
    }

also, the false should not be capitalized, but I'm sure in your code it is already not capitalized.

document.addEventListener('alpine:init', () => {
    Alpine.store('isSecondBlock', false);
    Alpine.store('sharedData', ["an", "array", "here"]);
}
  • Related