<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://joshhanley.au/articles</id>

    <title>Josh Hanley</title>

    <updated>2021-01-11T12:04:18+11:00</updated>

    <author>
        <name> <![CDATA[Josh Hanley]]></name>
    </author>

    <link rel="self" href="https://joshhanley.au/feed" />

            <entry>
            <title><![CDATA[How to structure your layout file for Livewire]]></title>
            <link rel="alternate" href="https://joshhanley.au/articles/how-to-structure-your-layout-file-for-livewire" />
            <id>https://joshhanley.au/articles/how-to-structure-your-layout-file-for-livewire</id>
            <author>
                <name> <![CDATA[Josh Hanley]]></name>
            </author>
            <summary type="html">
                <![CDATA[<p>In the previous article “<a rel="noopener noreferrer" target="_blank" class="external-link" href="https://joshhanley.com.au/articles/how-to-use-layout-components-in-livewire">How to use layout components in Livewire</a>” we went through setting up an app layout component that Livewire can find. This article goes through setting up its contents for use with Livewire by adding the Livewire tags and going through a way to manage your header and page title.</p>
]]>
            </summary>
            <content type="html">
                <![CDATA[
                    <p>In the previous article “<a rel="noopener noreferrer" target="_blank" class="external-link" href="https://joshhanley.com.au/articles/how-to-use-layout-components-in-livewire">How to use layout components in Livewire</a>” we went through setting up an app layout component that Livewire can find. This article goes through setting up its contents for use with Livewire by adding the Livewire tags and going through a way to manage your header and page title.</p>
                    <h2>The default app layout</h2>
<p>Now that your layout component is configured to be recognised automatically by Livewire, it’s time to setup its contents to get Livewire running. </p>
<p>Open up your <code>app.blade.php</code> file.</p>
<p>If you are using a front end scaffolding like Laravel Breeze or Jetstream, or upgrading the layout file in an existing app, then you will already have a layout similar to below. </p>
<p>If you aren’t, you can always copy it from <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://github.com/laravel/breeze/blob/1.x/stubs/resources/views/layouts/app.blade.php">Laravel Breeze</a> as it is a great starting point. But you will need to modify it as it contains asset links for <code>app.css</code> and <code>app.js</code>, which will need to be compiled, and that is not covered in this tutorial (just remove them if you won’t be using them).</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;{{ str_replace('_', '-', app()-&gt;getLocale()) }}&quot;&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
        &lt;meta name=&quot;csrf-token&quot; content=&quot;{{ csrf_token() }}&quot;&gt;

        &lt;title&gt;{{ config('app.name', 'Laravel') }}&lt;/title&gt;

        &lt;!-- Fonts --&gt;
        &lt;link rel=&quot;stylesheet&quot; href=&quot;https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&amp;display=swap&quot;&gt;

        &lt;!-- Styles --&gt;
        &lt;link rel=&quot;stylesheet&quot; href=&quot;{{ asset('css/app.css') }}&quot;&gt;

        &lt;!-- Scripts --&gt;
        &lt;script src=&quot;{{ asset('js/app.js') }}&quot; defer&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body class=&quot;font-sans antialiased&quot;&gt;
        &lt;div class=&quot;min-h-screen bg-gray-100&quot;&gt;
            @include('layouts.navigation')

            &lt;!-- Page Heading --&gt;
            &lt;header class=&quot;bg-white shadow&quot;&gt;
                &lt;div class=&quot;max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8&quot;&gt;
                    {{ $header }}
                &lt;/div&gt;
            &lt;/header&gt;

            &lt;!-- Page Content --&gt;
            &lt;main&gt;
                {{ $slot }}
            &lt;/main&gt;
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2>The Livewire app layout</h2>
<p>The first thing to do when you setup Livewire in any app, is to configure Livewire’s styles and scripts tags (see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/installation#include-js">Include The Assets</a>).</p>
<p>To do this, we are going to use the blade component tag syntax, so it is consistent with the app layout component we have already setup.</p>
<p>In your <code>app.blade.php</code> file, you need to add <code>&lt;livewire:styles /&gt;</code> inside the <code>&lt;head&gt;</code> tags. I would recommended adding it after any other css stylesheets or style tags you may have, to ensure the Livewire styles have priority, as they contain some visibility and animation keyframe styles that Livewire needs to work.</p>
<p>Then you need add <code>&lt;livewire:scripts /&gt;</code> to the end of you body tag right before the closing <code>&lt;/body&gt;</code> tag. This ensure’s that Livewire runs after the page has finished loading. </p>
<p><strong>But there is a catch</strong>. If you are installing Livewire into an existing app, you may already have some script tags or javascript assets added to the end of your body tag. If this is the case, then you need to make sure you put Livewire’s scripts first, before any other javascript libraries or script tags. Otherwise if you try to call any of Livewire’s javascript functions from any of these script tags or javascript files, then you will get errors.</p>
<blockquote>
<p>NOTE: Put Livewire’s script tags at the end of the body, just before the closing <code>&lt;/body&gt;</code> tag but <strong>before any other javascript libraries or script tags</strong>.  </p>
</blockquote>
<p>Your layout file should now look something like the below. I have removed most things from the <code>&lt;head&gt;</code> tags just to make the example shorter.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;{{ str_replace('_', '-', app()-&gt;getLocale()) }}&quot;&gt;
    &lt;head&gt;
        &lt;!-- head content removed to keep it small --&gt;
        &lt;livewire:styles /&gt;
    &lt;/head&gt;
    &lt;body class=&quot;font-sans antialiased&quot;&gt;
        &lt;div class=&quot;min-h-screen bg-gray-100&quot;&gt;
            @include('layouts.navigation')

            &lt;!-- Page Heading --&gt;
            &lt;header class=&quot;bg-white shadow&quot;&gt;
                &lt;div class=&quot;max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8&quot;&gt;
                    {{ $header }}
                &lt;/div&gt;
            &lt;/header&gt;

            &lt;!-- Page Content --&gt;
            &lt;main&gt;
                {{ $slot }}
            &lt;/main&gt;
        &lt;/div&gt;

        &lt;livewire:scripts /&gt;
        &lt;!-- Any other script tags or libraries here --&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>With this setup Livewire will auto populate <code>{{ $slot }}</code> with the contents of your Livewire component blade file.</p>
<p>So you should be all ready to go to start creating components.</p>
<p><em>The rest of this article assumes you know how to setup and use a Livewire component, if not please see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/making-components">Making Components</a> and <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/rendering-components">Rendering Components</a> in the Livewire docs.</em></p>
<h2>But what about the header?</h2>
<p>You may have noticed that there is a header in the default Breeze layout, which outputs the contents of the <code>{{ $header }}</code> variable. </p>
<p>But if any of you actually tried to setup a component using this layout by now, will know that we would currently be getting an error “Undefined variable: header”.</p>
<p>The <code>$header</code> variable is populated using a named slot (see the last section of <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel.com/docs/8.x/blade#slots">Blade Templates - Slots</a>).</p>
<p>You can populate the header slot by adding the <code>x-slot</code> tag with the name <code>header</code> at the top of your Livewire component blade file.</p>
<pre><code class="language-html">&lt;x-slot name=“header”&gt;
    &lt;!-- Some header content here --&gt;
&lt;/x-slot&gt;

&lt;div&gt;
    &lt;!-- Livewire component content here --&gt;
&lt;/div&gt;
</code></pre>
<p>Now you may have seen in the Livewire docs <strong>“Make sure your Blade view only has ONE root element.”</strong> (See <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/rendering-components#returning-blade">Returning Blade Views</a>). </p>
<p>This is the only exception to this rule, as the blade compiler will actually remove the <code>&lt;x-slot&gt;</code> tags and their contents, and insert them into the correct location in the layout file.</p>
<h2>Making the header interactive</h2>
<p>With your header slot all configured, you may get to a point where you want to add a create button inside your page heading.</p>
<p>That should be simple enough, inside your Livewire component blade file, populate the <code>&lt;x-slot&gt;</code> tags for your header with a button and add <code>wire:click</code> to it . Making sure your Livewire component class has the corresponding method (but that is outside the scope of this tutorial).</p>
<pre><code class="language-html">&lt;x-slot name=“header”&gt;
    &lt;button type=&quot;button&quot; wire:click=&quot;create&quot;&gt;Create!&lt;/button&gt;
&lt;/x-slot&gt;

&lt;div&gt;
    &lt;!-- Livewire component content here --&gt;
&lt;/div&gt;
</code></pre>
<p>Once added, refresh your page, click “Create!” and BAM! Nothing happens…</p>
<p>Not what you expected.</p>
<p>The reason is that, although the header slot contents were saved in the Livewire component blade file, when its rendered, those contents were actually outside of the area which Livewire can control. The area it currently has control of is everything inside <code>{{ $slot }}</code>.</p>
<p>If you look back at our layout you will see <code>{{ $header }}</code> is above this, so the blade compiler removes the header  <code>&lt;x-slot&gt;</code> tags and contents from our Livewire component blade file, and adds them into the layout here. </p>
<p>This makes it inaccessible to Livewire which means the <code>wire:click</code> on the button won’t do anything.</p>
<h2>How do we fix this?</h2>
<p>First we change the body tags in our <code>app.blade.php</code> layout file to only have a slot and Livewire scripts (and any other javascript libraries and script tags).</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;{{ str_replace('_', '-', app()-&gt;getLocale()) }}&quot;&gt;
    &lt;head&gt;
        &lt;!-- head content removed to keep it small --&gt;
        &lt;livewire:styles /&gt;
    &lt;/head&gt;
    &lt;body class=&quot;font-sans antialiased&quot;&gt;
        {{ $slot }}

        &lt;livewire:scripts /&gt;
        &lt;!-- Any other script tags or libraries here --&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Then we can create a page layout component with everything we just took out of the body tag.</p>
<p>Create a file called <code>page.blade.php</code> in out layouts folder.</p>
<pre><code class="language-bash">resources/views/layouts/page.blade.php
</code></pre>
<p>Open it and add all the layout information we removed from the body tags (note it will also have it’s own <code>{{ $slot }}</code> tag).</p>
<pre><code class="language-html">&lt;div class=&quot;min-h-screen bg-gray-100&quot;&gt;
    @include('layouts.navigation')

    &lt;!-- Page Heading --&gt;
    &lt;header class=&quot;bg-white shadow&quot;&gt;
        &lt;div class=&quot;max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8&quot;&gt;
            {{ $header }}
        &lt;/div&gt;
    &lt;/header&gt;

    &lt;!-- Page Content --&gt;
    &lt;main&gt;
        {{ $slot }}
    &lt;/main&gt;
&lt;/div&gt;
</code></pre>
<p>Again to get this to work as a component, we would have to follow the same process as we used in the previous article, to create an inline blade component, this time for the page layout.</p>
<pre><code class="language-bash"># Creates app/View/Components/PageLayout.php
php artisan make:component PageLayout --inline
</code></pre>
<p>Open <code>PageLayout.php</code> and change the render method to point to the new page layout view.</p>
<pre><code class="language-php">// app/View/Components/PageLayout.php
public function render()
{
    // Resolves to resources/views/layouts/page.blade.php
    return view('layouts.page');
}
</code></pre>
<p>Then back in your Livewire component blade view, just wrap everything you had in your <code>&lt;x-page-layout&gt;</code> tags.</p>
<pre><code class="language-html">&lt;x-page-layout&gt;
    &lt;x-slot name=“header”&gt;
        &lt;button type=&quot;button&quot; wire:click=&quot;create&quot;&gt;Create!&lt;/button&gt;
    &lt;/x-slot&gt;

    &lt;div&gt;
        &lt;!-- Livewire component content here --&gt;
    &lt;/div&gt;
&lt;/x-page-layout&gt;
</code></pre>
<p>Now go back to your browser, refresh, and click on that “Create!” button in the header.</p>
<p>It should now work! Success!</p>
<h2>The page title</h2>
<p>The last thing which is common to want to set, in your app layout, is the page title.</p>
<p>The default title in the head section of the Breeze layout looks like this.</p>
<pre><code class="language-html">&lt;title&gt;{{ config('app.name', 'Laravel') }}&lt;/title&gt;
</code></pre>
<p>But you may want to specify a different title for each page of your app, or have a default if there is no title specified.</p>
<p>So I would recommend changing it to a named slot, for title, with a fall back of your app name.</p>
<pre><code class="language-html">&lt;title&gt;{{ $title ?? config('app.name', 'Laravel') }}&lt;/title&gt;
</code></pre>
<p>This will allow us to populate the title of the page by passing it through the title named slot.</p>
<p>There are two ways to do this with Livewire which I will list below. </p>
<p>But be aware, no matter which method you use, Livewire will only set the title of the page on the first load. So if you try to change it in a subsequent request, within the same component, it won't change. If you need to do that, you will need to use javascript to do this.</p>
<blockquote>
<p>Livewire will only set the title of the page on the first load.</p>
</blockquote>
<p>One way is to add the title named slot, which contains your desired title, to the top of our Livewire component's blade view, like we originally did for header (but outside the page layout tags). The title will only take a string so I wouldn't be trying to add any html to this.</p>
<pre><code class="language-html">&lt;x-slot name=&quot;title&quot;&gt;Our new page title&lt;/x-slot&gt;

&lt;x-page-layout&gt;
    &lt;x-slot name=“header”&gt;
        &lt;button type=&quot;button&quot; wire:click=&quot;create&quot;&gt;Create!&lt;/button&gt;
    &lt;/x-slot&gt;

    &lt;div&gt;
        &lt;!-- Livewire component content here --&gt;
    &lt;/div&gt;
&lt;/x-page-layout&gt;
</code></pre>
<p>The other way is to specify it in the render method in your component class, by passing it as a data property into the layout method (see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/rendering-components#custom-layout">Configuring the Layout Component</a>).</p>
<pre><code class="language-php">public function render() {
    return view('sample-component')
        -&gt;layout('layouts.app', ['title' =&gt; 'Our new page title']);
}
</code></pre>
<p>The downside to this method is you need to specify the app layout for this to work.</p>
<p>Your app layout should now be all configured and ready to go. </p>
<p>If you have any questions or I have missed anything, please let me know.</p>
<p>Hope this helps!</p>
                    ]]>
            </content>
            
            
            <updated>2021-01-11T12:00:43+11:00</updated>
            <published>2021-01-11T12:00:43+11:00</published>
        </entry>
            <entry>
            <title><![CDATA[How to use layout components in Livewire]]></title>
            <link rel="alternate" href="https://joshhanley.au/articles/how-to-use-layout-components-in-livewire" />
            <id>https://joshhanley.au/articles/how-to-use-layout-components-in-livewire</id>
            <author>
                <name> <![CDATA[Josh Hanley]]></name>
            </author>
            <summary type="html">
                <![CDATA[<p>How to make an app layout component that can be used in your blade views and automatically used by full page Livewire components.</p>
]]>
            </summary>
            <content type="html">
                <![CDATA[
                    <p>How to make an app layout component that can be used in your blade views and automatically used by full page Livewire components.</p>
                    <h2>Setting up a layout component</h2>
<p>Recently I converted my app to use <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel.com/docs/8.x/blade#components">blade components</a> and one of the components I setup was for my app layout.</p>
<p>My original app layout file was stored at <code>resources/views/layouts/app.blade.php</code> and used <code>@yield</code> syntax (see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel.com/docs/8.x/blade#layouts-using-template-inheritance">Layouts Using Template Inheritance</a>)</p>
<p>To make this a blade component, I moved the file to <code>resources/views/components/layouts/app.blade.php</code> and changed it to use the <code>{{ $slot }}</code> syntax (see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel.com/docs/8.x/blade#layouts-using-components">Layouts Using Components</a>).</p>
<p>This allowed me to wrap the contents of a blade view in an app layout tag like <code>&lt;x-layouts.app&gt;</code> instead of using <code>@extends</code> and <code>@section</code> tags.</p>
<pre><code class="language-html">&lt;x-layouts.app&gt;
&lt;!-- content here --&gt;
&lt;/x-layouts.app&gt;
</code></pre>
<p>Now all my blade views can make use of that app layout component tag.</p>
<h2>That layout component doesn’t work with Livewire (yet)</h2>
<p>Out of the box, that app layout component won’t work with Livewire though.</p>
<p>When I started using Livewire, I saw that Livewire automatically uses the app layout file and populates <code>{{ $slot }}</code> for you (see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/rendering-components#page-components">Full Page Components</a>).</p>
<p>That meant I didn’t need to wrap the contents of my full page Livewire component blade views with the app layout tag, as Livewire will handle that.</p>
<p>But for some reason that didn’t work. Nothing would load.</p>
<p>If you look closely at the <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/rendering-components#page-components">full page components</a> docs though, you will find that Livewire is actually looking for your app layout file in the old layouts location <code>resources/views/layouts/app.blade.php</code>, not in the components directory.</p>
<p>So Livewire can’t find find our newly created app layout component, as it’s looking in a different location.</p>
<p>To work around this, you have to resort to manually specifying it in your full page Livewire component’s render method, like this</p>
<pre><code class="language-php">public function render()
{
return view('livewire.sample-component')
-&gt;layout('components.layouts.app');
}
</code></pre>
<p>That’s painful though, as you have to specify this inside the render method of every full page Livewire component (trust me as I did this).</p>
<p>But there is another way.</p>
<h2>The new app layout in the old app layout location</h2>
<p>There is a technique you can use which makes use of a blade component class to point at a blade view file that is stored in a different location.</p>
<p>Take the new app layout component blade file, that uses the <code>{{ $slot }}</code> syntax, and move it back to the old location <code>resources/views/layouts/app.blade.php</code>, but keep the new syntax.</p>
<p>You can then create an <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel.com/docs/8.x/blade#inline-component-views">inline blade component</a> called Layouts/App</p>
<pre><code class="language-bash">php artisan make:component Layouts/App --inline
</code></pre>
<p>Which generates this blade component php class (but no corresponding blade view)</p>
<pre><code class="language-bash">app/View/Components/Layouts/App.php
</code></pre>
<p>Open up the newly create class and look at the render method, it will look something like this</p>
<pre><code class="language-php">public function render()
{
return &lt;&lt;&lt;'blade'
&lt;div&gt;
&lt;!-- An unexamined life is not worth living. - Socrates --&gt;
&lt;/div&gt;
blade;
}
</code></pre>
<p>Inside the render method, delete all the heredoc code (everything inside the render method) and instead you can return your app layout view (which we moved back out of the components directory earlier)</p>
<pre><code class="language-php">// app/View/Components/Layouts/App.php
public function render()
{
// Resolves to resources/views/layouts/app.blade.php
return view('layouts.app');
}
</code></pre>
<p>Now we are back to the way it was before, where you can use your app layout as component tags inside your standard blade views</p>
<pre><code class="language-html">&lt;x-layouts.app&gt;
&lt;!-- content here --&gt;
&lt;/x-layouts.app&gt;
</code></pre>
<p>Livewire can now also find it in the correct location, so you don’t need to use the layout method inside your Livewire render method. So you render should look something like this</p>
<pre><code class="language-php">// Your Livewire component class
public function render()
{
// This auto finds the layout in resources/views/layouts/app.blade.php
return view('livewire.sample-component');
}
</code></pre>
<p>That’s all there is to setting up a layout component that can be used in blade templates and by full page Livewire components (without having to specify it each time).</p>
<p>Read on if you want to look at how to change the layout tag to a different name that Laravel Breeze and Jetstream both use.</p>
<h2>A better layout tag name</h2>
<p>Laravel Breeze and Jetstream both make use of <code>&lt;x-app-layout&gt;</code> as their layout tag.</p>
<p>It would be much nicer if we could actually use <code>&lt;x-app-layout&gt;</code> for the tag as I find it reads better than <code>&lt;x-layouts.app&gt;</code>. It also means we don’t have a component class file called <code>App.php</code> which could be confused with other app references.</p>
<p>If you prefer this, you can move the <code>Layouts/App.php</code> php class file that we generated earlier to the base components class directory and rename it</p>
<pre><code class="language-bash">app/View/Components/AppLayout.php
</code></pre>
<p>Make sure you also open the file and change the class name to <code>AppLayout</code>.</p>
<p>Now your blade views can look like this</p>
<pre><code class="language-html">&lt;x-app-layout&gt;
&lt;!-- content here --&gt;
&lt;/x-app-layout&gt;
</code></pre>
<p>And Livewire shouldn’t be impacted as we didn’t touch the app layout blade view.</p>
<p>This is how Laravel Breeze and Jetstream both handle this, see example in their respective GitHub repositories below.<br />
<a rel="noopener noreferrer" target="_blank" class="external-link" href="https://github.com/laravel/breeze/blob/1.x/stubs/App/View/Components/AppLayout.php">breeze/AppLayout.php · GitHub</a><br />
<a rel="noopener noreferrer" target="_blank" class="external-link" href="https://github.com/laravel/jetstream/blob/1.x/stubs/livewire/app/View/Components/AppLayout.php">jetstream/AppLayout.php · GitHub</a></p>
<p><strong>Update:</strong><br />
The second part to this has been published, check it out <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://joshhanley.com.au/articles/how-to-structure-your-layout-file-for-livewire">How to structure your layout file for Livewire</a>.</p>
<p>Hope this helps!</p>
                    ]]>
            </content>
            
            
            <updated>2021-01-11T12:04:18+11:00</updated>
            <published>2020-12-22T06:34:48+11:00</published>
        </entry>
            <entry>
            <title><![CDATA[Why Livewire and why this blog?]]></title>
            <link rel="alternate" href="https://joshhanley.au/articles/why-livewire-and-why-this-blog" />
            <id>https://joshhanley.au/articles/why-livewire-and-why-this-blog</id>
            <author>
                <name> <![CDATA[Josh Hanley]]></name>
            </author>
            <summary type="html">
                <![CDATA[<p>This article goes into why my excitement for Livewire led me to use it in my apps, contribute on GitHub and start this blog. Read this to find out how my Livewire journey began.</p>
]]>
            </summary>
            <content type="html">
                <![CDATA[
                    <p>This article goes into why my excitement for Livewire led me to use it in my apps, contribute on GitHub and start this blog. Read this to find out how my Livewire journey began.</p>
                    <h2>The desire</h2>
<p>I’ve been watching the development of Livewire since v1 was released at Laracon in March 2019.</p>
<p>I loved the idea that everything was written in php and blade, which reduces my need to use javascript frameworks.</p>
<p>My main app had a mix of standard blade pages and some with small VueJS components mixed in. None of the Vue code in my app was unit tested. I don’t like switching contexts between blade and Vue when coding. Plus passing data from blade into Vue never felt great.</p>
<p>As you can imagine I was keen to convert my app over to Livewire and remove Vue. I started experimenting with it, make small test apps that contain some of the components my main app would need.</p>
<h2>The delay</h2>
<p>But converting my Vue code to Livewire had to wait. Even though this only added to my desire to get started, important things had to happen first.</p>
<p>I was in the process of converting my app from blade partials to blade components while also doing a redesign. Livewire integration would have to wait until that was all done.</p>
<p>While I was finishing the conversion, v2 of Livewire was released, in September 2020, with a whole heap of quality of life/ development improvements. That really solidified my desire to use Livewire in my app.</p>
<p>I finished the conversion to blade components around mid-October 2020, except for one complex form that was using Vue components for interactivity.</p>
<p>I’d intentionally left this form out, as it presented a good opportunity to finally get stuck into using Livewire, as it required interactivity. My intent was that I’d convert from Vue straight to Livewire and implement any blade components as I went along.</p>
<h2>The start</h2>
<p>This seemed like it was going to be pretty straight forward.</p>
<p>One of the core components in this form is that it has autocomplete inputs which integrate together. A complex task that has been done many times before.</p>
<p>What it needs to be able to do is filter (cascade) the results of one autocomplete input based upon the options selected in previous inputs; or have the option to auto populate multiple input fields based upon the selection in one dropdown.</p>
<p>So naturally, I jumped right into trying to build an autocomplete dropdown component using Livewire and AlpineJS.</p>
<p>For the AlpineJS side, I had just seen a great tutorial by Dan Harrin on <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://youtu.be/L_f9gNaSCRE">“Building a custom select input with Alpine.js and Tailwind CSS”</a>. I used his ideas as base for creating my Livewire/Alpine autocomplete.</p>
<p>I got an Alpine autocomplete working quite quickly with static data thanks to Dan’s tutorial, and started trying to integrate data from Livewire.</p>
<p>That’s when it all fell apart.</p>
<h2>The problem</h2>
<p>V2 of Livewire introduced a new feature called <code>@entangle</code> (see <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://laravel-livewire.com/docs/2.x/alpine-js">Sharing State Between Livewire And Alpine: @entangle</a>). This offered the promise of syncing properties between Livewire and Alpine.</p>
<p>But as it was a new feature, it had some bugs. I opened a couple of issues on the Livewire GitHub along with some PR’s which added failing tests demonstrating the issues.</p>
<p>Now there were certainly work arounds, I could have gone back to managing the syncing of properties myself like others had done before entangle became available in V2. But I believed that entangle was a really handy feature, and with a few bug fixes, should work quite nicely.</p>
<p>At the time, I didn’t know much about how Livewire operates, so couldn’t be of much help fixing the entangle problems.</p>
<h2>The solution</h2>
<p>What I could do though, was help with issues that other people might be having, which has the benefit that I will learn more about Livewire in the process (and maybe it’ll free Caleb up to fix these more complicated bugs 😆).</p>
<p>I started going through the Livewire issues on GitHub and spending time on the <a rel="noopener noreferrer" target="_blank" class="external-link" href="https://discord.gg/livewire">Livewire Discord</a> helping other people out with their problems.</p>
<p>I found that I really enjoyed helping others fix their problems. I’d previously worked for about 8 years in IT support, but there is a big difference between fixing general computer problems and trying to work out why someone’s Livewire code doesn’t run properly. Certainly a lot more interesting!</p>
<p>Plus I got to know a lot of Livewire’s features really well, through taking a problem someone was having, running their code, and experimenting with it trying to get it to run. A lot of the time it sent me digging through the documentation or Livewire core code to find out exactly how something works, to be able to better understand the solution.</p>
<p>This has the added benefit that it makes developing my apps quicker and smoother as I’m familiar with the common problems, have a better understanding of how it all works together, and know what features are available.</p>
<h2>The blog</h2>
<p>That’s where this blog comes in.</p>
<p>Up until now, I didn’t have a personal website or blog, as I wasn’t exactly sure of what I would write about.</p>
<p>But, as I’m solving problems I am finding a lot of interesting ways to achieve things and fix common problems, that I’d like to document and share so others can benefit from it.</p>
<p>So that’s how this blog began.</p>
<p>I hope that the content here can be useful to someone. Feel free to contact me on twitter or discord if have any questions, ideas or just want to chat!</p>
<p>And as always,</p>
<p>Hope this helps!<br />
Josh</p>
                    ]]>
            </content>
            
            
            <updated>2020-12-18T16:23:39+11:00</updated>
            <published>2020-12-18T12:11:18+11:00</published>
        </entry>
    </feed>
