Just released

Introducing livewire-petite-vue

Samuel Štancl

Samuel Štancl

Founder

Published on

We've just released the first version of our package which provides support for using petite-vue in Livewire.

Here's a quick showcase of how it's used:

<script type="module">
    import { createApp } from 'https://unpkg.com/@archtechx/livewire-petite-vue'

    // We mount Vue after Livewire initializes its frontend runtime
    window.addEventListener('livewire:load', () => {
        createApp().mount()
    })
</script>

<!--
    The v-livewire directive lets us connect Vue properties to LW properties
     
    v-livewire="{ messages: 'items' }" to connect Vue 'messages' to LW 'items'
    v-livewire="['messages']" is a shorthand for { messages: 'messages' }

    You can also v-livewire.defer the binding.
-->
<div v-livewire="['messages']" v-scope="{ messages: {}, foo: 'bar' }">
    You can use Vue-only state in the component: {{ foo }}
    <input v-model="foo">

    <!--
        Fully shared state. Any changes from LW are immediately
        reflected in Vue, and the same applies from Vue to LW.
     -->
    <template v-for="(message, id) in messages">
        <div>
            <div>
                <label :for="`message-${id}`">Message</label>

                <!-- input -> Vue property -> Livewire property -> server -->
                <input :id="`message-${id}`" v-model.lazy="messages[id].message">
            </div>

            <!-- Use the wire property to access the component -->
            <button type="button" @click="wire.send(id)">
                Send
            </button>

            <button type="button" @click="wire.remove(id)">
                Remove
            </button>
        </div>
    </template>
</div>

Why petite-vue?

Most Livewire applications will choose to use Alpine.js for frontend interactivity. Alpine is a great library with an existing Livewire integration, reasonably growing ecosystem, and a good community.

However, some developers are coming from the Vue.js community, or want to use (petite-vue-compatible) Vue libraries. For that purpose, our library provides a great way to get started with Livewire in a more familiar way.

The Alpine ecosystem will presumably always have more Livewire-specific projects, but with a 5kb runtime, there's nothing stopping you from leveraging the vue-petite features and ecosystem as well.

Features

The package provides:

  • bridge for bidirectional linking between Vue state and Livewire state
  • wire proxy that can be used to access any Livewire property or method right from your Vue code
wire.foo('bar');

await wire.bar();

wire.foo = 'bar';

The bridge — enabled using the v-livewire directive — can use deferred binding to Livewire properties:

<div v-livewire.defer="['messages']" v-scope="{ messages: {} }">

One thing to keep in mind is that you always need to define initial Vue state, as Vue will first render the component with the original Vue state before executing the v-livewire directive.

And with those simple changes, you can use Vue properties and have them immediately sync with Livewire.

Roadmap

The package is currently in 0.1.0. Since petite-vue is still a very early project, changes can be expected. For instance, we hope to change the v-livewire syntax to something similar to Alpine's entangle, e.g. v-scope="{ messages: wire.messages }".

That said, the package is completely usable and we're already using it in some internal projects.

Contributions

The repository can be found on GitHub.

Right now, there's also a help wanted issue open — the package is a simple .js file, but we'd like a more optimized build with separate files, <script src="..." init> and npm support (potentially TypeScript support as well).

The bounty on that issue is $50, so if you're proficient in JS, interested in this project, and would like to help out, feel free to send a pull request and we'll be more than happy to pay you for your effort.

As with all other ArchTech projects, we appreciate community contributions and love to discuss ways to make our work more valuable.