In my previous post on this topic, I described a way to transfer data into an Alpine component, if the page has been rendered by PHP on the server.
This is often going to be the situation when I’m using Alpine JS to add some interactivity to the page. For example, Alpine might need the data in an x-show condition, in an x-model input field, or to drive dynamic CSS with x-bind.
An alternative, of course, is to fetch the data from an API after the page has loaded. But this would be duplicating time and effort. PHP has already rendered the page, including the data I need, so it’s just a matter of getting the data over into the Alpine variables.
The solution I’ve devised is x-json, an Alpine custom directive. The code for the directive is in my previous post, and now I just want to give a bit more detail on its usage.
The directive is applied to a JS script element, containing JSON data, that PHP must first render into the page. Again, my previous post gave an example of how this is done, but you would end up with something like this in your page. One important note – this script must be inside the x-data scope that you want to populate.
<script type="application/json">
{"student":{"name":"Sue","age":32"},"locations":["Paris","London"]}
</script>
In this case the data is an object, consisting of two named objects. One is an object with student data, the other an array of locations. I want to put all of that data into this Alpine component:
Alpine.data('mydata',() => ({
student: {},
locations: [],
}))
Note that the names of the Alpine properties must match the names in the JSON object. I don’t see this as a serious constraint, and it keeps things simple.
Now to connect things up, I simply add the directive to the script tag:
<script type="application/json" x-json>
Now the directive will copy the JSON data into the Alpine component. Remember that the script must be placed inside the x-data scope for the component.
If for some reason I don’t want to copy all the data – say just the student object, then I add a modifier to the directive.
<script type="application/json" x-json.student>
Maybe the locations array has to go in an Alpine store, so I add another x-json directive, this time with the store name (prefixed by a colon) and a modifier.
<script type="application/json" x-json.student x-json:mystore.locations>
I can chain several modifiers together, so (if the JSON also contained a ‘lessons’ object for the Alpine store), I could do this:
<script type="application/json" x-json.student x-json:mystore.locations.lessons>
One last thing – the directive runs after the x-init and init() functions. If you need to do some processing after the JSON data arrives in the component or store, you can nominate a callback function. Maybe something like this:
<script type="application/json" x-json.student="switch()">
The ‘switch()’ function in the Alpine component will now be called after the student data is copied in. Note that if you want to use a function in an Alpine store, you have to supply the fully qualified function name. If you just supply a function name, it refers to a function in the current data component.
<script type="application/json" x-json:mystore.locations="$store.mystore.storeLoaded()">
And that’s it … for now. If I develop any new features, I’ll post them here.