In this lesson, we’ll focus on managing component state using EdgeJS and how we can pass state from EdgeJS into AlpineJS.
EdgeJS State
The easiest way that we can set state within an EdgeJS Component is via the set tag (@set). The set tag is going to allow us to set a local variable that will only exist inside of this particular component.
When defined at the top of our component file, it’ll be unique to its particular component instance and won’t be shared with other components or pages.
When defined inside a block, like an @each or @if, it’ll exist only inside that block. Similar to a tradition JavaScript variable.
@set('breadcrumbs', false)Copied!
The set tag is a simple method, which tags the variable’s name as the first argument and the value as the second argument. The value here can be a number of different valid JavaScript values, including arrow functions, objects, arrays, and primitive types.
Passing Primitives from EdgeJS to AlpineJS
Let’s say we want to pass the EdgeJS variable we’ve set above, called breadcrumbs, as the default value for our breadcrumbs variable in our AlpineJS state. Since the value is a primitive type, all we’ll need to do is drop it directly from EdgeJS into the value position for AlpineJS.
@set('breadcrumbs', false) <header x-data="{ breadcrumbs: {{ breadcrumbs }} }" x-data="{ breadcrumbs: true }" class="bg-gray-100 p-6 -mx-6 mb-6 rounded-md"> @if (title != 'Home') <a x-show="breadcrumbs" href="/" class="text-xs" @click.prevent="breadcrumbs = false"> Home </a> @endif <h1 class="text-2xl font-bold">{{ titleCase(title) }}</h1> </header>Copied!
- resources
- views
- components
- layouts
- app.edge
When EdgeJS renders this out on the server-side, it’ll end up looking like the below.
<header x-data="{ breadcrumbs: false }" class="bg-gray-100 p-6 -mx-6 mb-6 rounded-md"> <a x-show="breadcrumbs" href="/" class="text-xs" @click.prevent="breadcrumbs = false"> Home </a> <h1 class="text-2xl font-bold">Home</h1> </header>Copied!
Notice how {{ breadcrumbs }} simply renders to false.
Passing Objects & Arrays from EdgeJS to AlpineJS
When it comes to non-primitive types, however, things get a little more complicated because we can’t just directly pass an object or array from our server to client via HTML.
What Won’t Work
If we were to try passing an object from EdgeJS directly into AlpineJS as it’s state, like the below.
@set('data', { breadcrumbs: false }) <header x-data="{{ breadcrumbs }}" class="bg-gray-100 p-6 -mx-6 mb-6 rounded-md"> @if (title != 'Home') <a x-show="breadcrumbs" href="/" class="text-xs" @click.prevent="breadcrumbs = false"> Home </a> @endif <h1 class="text-2xl font-bold">{{ titleCase(title) }}</h1> </header>Copied!
- resources
- views
- components
- layouts
- app.edge
The final HTML output would end invalid, like the below.
<header x-data="[object Object]" class="bg-gray-100 p-6 -mx-6 mb-6 rounded-md"> <a x-show="breadcrumbs" href="/" class="text-xs" @click.prevent="breadcrumbs = false"> Home </a> <h1 class="text-2xl font-bold">Home</h1> </header>Copied!
Notice, how our EdgeJS data rendered as [object Object].
What Will Work
To remedy this, all we need to do is convert our object, or array, to a string. Though EdgeJS will be rendering a string on the server-side, once it hit’s our client-side it’ll come through as the object we had intended.
EdgeJS also has a global helper to aid with this, called stringify, which will not only convert our object to a string, but will also escape unsafe HTML characters to prevent XSS attacks.
@set('data', { breadcrumbs: false }) <header x-data="{{ stringify(breadcrumbs) }}" class="bg-gray-100 p-6 -mx-6 mb-6 rounded-md"> @if (title != 'Home') <a x-show="breadcrumbs" href="/" class="text-xs" @click.prevent="breadcrumbs = false"> Home </a> @endif <h1 class="text-2xl font-bold">{{ titleCase(title) }}</h1> </header>Copied!
- resources
- views
- components
- layouts
- app.edge
Using stringify, EdgeJS will now render the above as the below.
<header x-data="{ breadcrumbs: false }" class="bg-gray-100 p-6 -mx-6 mb-6 rounded-md"> <a x-show="breadcrumbs" href="/" class="text-xs" @click.prevent="breadcrumbs = false"> Home </a> <h1 class="text-2xl font-bold">Home</h1> </header>Copied!
Thus, allowing us to easily pass non-primitive values from EdgeJS to AlpineJS.