# MingleJS MingleJS is a Laravel package that enables React and Vue components to be seamlessly integrated into Livewire applications. It creates "islands of interactivity" by rendering a div container server-side, then mounting the JavaScript component client-side, allowing developers to leverage the reactivity of modern JavaScript frameworks within a Livewire-driven application. The package provides a bridge between Livewire's server-side rendering capabilities and React/Vue's client-side interactivity. Components can receive initial data from PHP via `mingleData()`, and the JavaScript components gain access to a `wire` object that enables direct server method calls using Livewire's wire protocol, eliminating the need for separate AJAX calls with Axios or Fetch. ## Installation ### Install MingleJS via Composer Install the package and run the installer command to configure your Laravel application for MingleJS. ```bash # Install the package composer require ijpatricio/mingle # Run the installer to set up Vite config and layout files php artisan mingle:install # Optional: Install with demo component php artisan mingle:install --with-demo ``` ## Creating Mingle Components ### make:mingle Artisan Command The `make:mingle` command scaffolds both the Livewire PHP component and the corresponding JavaScript files for your chosen framework (React or Vue). ```bash # Create a React mingle component php artisan make:mingle react TodoList # Create a Vue mingle component php artisan make:mingle vue UserProfile # Specify a custom JavaScript file path php artisan make:mingle react Dashboard --jsfile=resources/js/dashboard/Dashboard.js # Force overwrite existing files php artisan make:mingle vue Settings --force ``` ## Livewire Component Setup ### HasMingles Interface and InteractsWithMingles Trait Create a Livewire component that implements `HasMingles` interface and uses the `InteractsWithMingles` trait. Define the JavaScript component path in `component()` and pass data to the frontend via `mingleData()`. ```php [ ['id' => 1, 'title' => 'Learn MingleJS', 'completed' => false], ['id' => 2, 'title' => 'Build awesome apps', 'completed' => false], ], 'user' => auth()->user()->name, ]; } // Server-side methods callable from JavaScript via wire public function addTodo(string $title): array { $todo = [ 'id' => rand(1000, 9999), 'title' => $title, 'completed' => false, ]; // Save to database here... return $todo; } public function toggleTodo(int $id): bool { // Toggle in database and return new state return true; } public function deleteTodo(int $id): void { // Delete from database } } ``` ## React Component Integration ### Registering React Components with mingleReact Create a JavaScript entry file that registers your React component with MingleJS. The component receives `wire` for server communication and `mingleData` containing the initial data from PHP. ```javascript // resources/js/todo-list/index.js import mingle from '@mingle/mingleReact.jsx' import TodoList from './TodoList.jsx' mingle('resources/js/todo-list/index.js', TodoList) ``` ```jsx // resources/js/todo-list/TodoList.jsx import React, { useState } from 'react' function TodoList({ wire, mingleData }) { const [todos, setTodos] = useState(mingleData.initialTodos) const [newTodo, setNewTodo] = useState('') const [loading, setLoading] = useState(false) const addTodo = async () => { if (!newTodo.trim()) return setLoading(true) try { // Call PHP method via Livewire wire const todo = await wire.addTodo(newTodo) setTodos([...todos, todo]) setNewTodo('') } catch (error) { console.error('Failed to add todo:', error) } finally { setLoading(false) } } const toggleTodo = async (id) => { const completed = await wire.toggleTodo(id) setTodos(todos.map(todo => todo.id === id ? { ...todo, completed } : todo )) } const deleteTodo = async (id) => { await wire.deleteTodo(id) setTodos(todos.filter(todo => todo.id !== id)) } return (

Welcome, {mingleData.user}!

setNewTodo(e.target.value)} placeholder="Add a new todo..." className="flex-1 px-3 py-2 border rounded" />
) } export default TodoList ``` ## Vue Component Integration ### Registering Vue Components with mingleVue Register Vue components similarly to React. The component receives `wire` and `mingleData` as props. You can also listen to Livewire events dispatched from the server using `wire.on()`. ```javascript // resources/js/counter/index.js import mingle from '@mingle/mingleVue' import Counter from './Counter.vue' mingle('resources/js/counter/index.js', Counter) ``` ```vue ``` ## Advanced Vue Integration ### createMingle for Custom Vue App Configuration Use `createMingle` instead of the default `mingle` function when you need to customize the Vue app instance, such as adding plugins, global properties, or Pinia stores. ```javascript // resources/js/advanced-app/index.js import { createMingle } from '@mingle/mingleVue' import App from './App.vue' import { createPinia } from 'pinia' // Custom notification plugin const notificationPlugin = { install: (app, options) => { app.config.globalProperties.$notify = (message, type = 'info') => { console.log(`[${type.toUpperCase()}] ${message}`) // Your notification logic here } } } createMingle('resources/js/advanced-app/index.js', ({ createApp, props, el, wire, mingleId, wireId, mingleData }) => { const app = createApp(App, props) // Add Pinia for state management app.use(createPinia()) // Add custom plugins app.use(notificationPlugin) // Add global properties app.config.globalProperties.$api = { baseUrl: '/api/v1', } // Mount the app app.mount(el) return true }) ``` ## Blade Integration ### @mingles Directive Add the `@mingles` Blade directive to your layout file to include the JavaScript for all registered Mingle components. This should be placed in your main layout, typically in the `` or before the closing `` tag. ```blade {{ config('app.name') }} @vite(['resources/css/app.css', 'resources/js/app.js']) @mingles @livewireStyles {{ $slot }} @livewireScripts ``` ```blade

Dashboard

``` ## Lazy Loading with Placeholders ### Livewire Lazy Attribute MingleJS components support Livewire's lazy loading feature. Add the `#[Lazy]` attribute to defer component loading, and define a `placeholder()` method to show a loading state. ```php

Loading chart data...

HTML; } public function mingleData(): array { return [ 'chartData' => $this->fetchChartData(), 'options' => ['responsive' => true], ]; } private function fetchChartData(): array { // Heavy database queries here return [ 'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'May'], 'datasets' => [ ['label' => 'Sales', 'data' => [12, 19, 3, 5, 2]], ], ]; } } ``` ## Configuration ### mingle.php Config File Publish and customize the MingleJS configuration to set the default JavaScript base path and configure React preamble for hot module replacement. ```php 'resources/js', /* |-------------------------------------------------------------------------- | React Preamble |-------------------------------------------------------------------------- | | Enable the React refresh preamble for hot module replacement during | development. This should be enabled when using React components. | */ 'react_preamble_enabled' => true, ]; ``` ## Server Events Communication ### Dispatching Events from PHP to JavaScript Use Livewire's dispatch mechanism to send events from PHP to your JavaScript components. Listen for these events in Vue using `wire.on()`. ```php [], ]; } public function markAsRead(int $notificationId): void { // Update database... // Dispatch event to JavaScript component $this->dispatch('notification-read', id: $notificationId, timestamp: now()->toISOString() ); } public function clearAll(): void { // Clear all notifications in database... $this->dispatch('notifications-cleared'); } } ``` ```vue ``` ## Summary MingleJS enables Laravel developers to create rich, interactive user interfaces by combining Livewire's server-side simplicity with the powerful component ecosystems of React and Vue. The primary use cases include building complex form interfaces with real-time validation, creating data visualization dashboards with charting libraries, implementing real-time collaborative features, and integrating third-party JavaScript widgets that require React or Vue. The `wire` object provides seamless communication between frontend and backend, allowing JavaScript components to call PHP methods directly and receive responses as promises. Integration follows a consistent pattern: create a Livewire component implementing `HasMingles`, define the JavaScript component path and initial data, then register the JavaScript component using `mingle()` or `createMingle()`. The architecture supports lazy loading for performance optimization, Livewire events for server-to-client communication, and full access to the Vue/React ecosystems including state management libraries like Pinia or Redux. This approach lets teams leverage existing JavaScript component libraries while maintaining the developer experience benefits of Livewire's wire protocol.