Symfony UX Vue.js
Symfony UX Vue.js is a Symfony bundle integrating Vue.js in Symfony applications. It is part of the Symfony UX initiative.
Vue.js is a JavaScript framework for building user interfaces. Symfony UX Vue.js provides tools to render Vue components from Twig, handling rendering and data transfers.
Symfony UX Vue.js supports Vue.js v3 only.
Installation
Note
This package works best with WebpackEncore. To use it with AssetMapper, see Using with AssetMapper.
Caution
Before you start, make sure you have StimulusBundle configured in your app.
Install the bundle using Composer and Symfony Flex:
1
$ composer require symfony/ux-vue
The Flex recipe will automatically set things up for you, like adding
.enableVueLoader()
to your webpack.config.js
file and adding code
to load your Vue components inside assets/app.js
.
Next, install a package to help Vue:
1 2
$ npm install -D vue-loader --force
$ npm run watch
That's it! Any files inside assets/vue/controllers/
can now be rendered as
Vue components.
Usage
The Flex recipe will have already added the registerVueControllerComponents()
code to your assets/app.js
file:
1 2 3 4
// assets/app.js
import { registerVueControllerComponents } from '@symfony/ux-vue';
registerVueControllerComponents(require.context('./vue/controllers', true, /\.vue$/));
This will load all Vue components located in the assets/vue/controllers
directory. These are known as Vue controller components: top-level
components that are meant to be rendered from Twig.
You can render any Vue controller component in Twig using the vue_component()
.
1 2 3 4 5 6 7 8 9 10
// assets/vue/controllers/Hello.vue
<template>
<div>Hello {{ name }}!</div>
</template>
<script setup>
defineProps({
name: String
});
</script>
1 2
{# templates/home.html.twig #}
<div {{ vue_component('Hello', { 'name': app.user.fullName }) }}></div>
Events
The event vue:before-mount
is called before a component is mounted on the page. This is the event to listen if you need to modifiy the Vue application (e.g.: add plugins, add global directives, states ...):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// assets/app.js
document.addEventListener('vue:before-mount', (event) => {
const {
componentName, // The Vue component's name
component, // The resolved Vue component
props, // The props that will be injected to the component
app, // The Vue application instance
} = event.detail;
// Example with Vue Router
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: [
/* ... */
],
});
app.use(router);
});
Note
When using Vue Router, you can use "hash" or "memory" history mode to prevent your Vue routes from being served through Symfony controllers. If you want to use web history mode, see Symfony UX Vue.js
The event vue:mount
is called when a component has been mounted on the page:
1 2 3 4 5 6 7
document.addEventListener('vue:mount', (event) => {
const {
componentName, // The Vue component's name
component, // The resolved Vue component
props, // The props that are injected to the component
} = event.detail;
});
The event vue:unmount
is called when a component has been unmounted on the page:
1 2 3 4 5 6
document.addEventListener('vue:unmount', (event) => {
const {
componentName, // The Vue component's name
props, // The props that were injected to the component
} = event.detail;
});
Web History mode with Vue Router
To use "web" history mode with Vue Router, a catch-all route will be needed which should render the same template and Vue component:
1 2 3 4 5
#Route('/survey/{path<.+>}')
public function survey($path = ''): Response
{
// render the template
}
This controller will catch any URL that starts with `/survey`. This prefix can then be used for all the Vue routes:
1 2 3 4 5 6 7 8 9 10
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes: [
{ path: '/survey/list', component: ListSurveys },
{ path: '/survey/create', component: CreateSurvey },
{ path: '/survey/edit/:surveyId', component: EditSurvey },
],
});
app.use(router);
Using with AssetMapper
The Vue single-file component (i.e. .vue
) file format is not pure JavaScript
and cannot currently be converted to pure JavaScript outside of a bundler like
Webpack Encore or Vite. This means that the .vue
file format cannot be used
with AssetMapper.
If you do still want to use Vue with AssetMapper, you can do so by avoiding
the .vue
file format. For example, https://github.com/symfony/ux/blob/2.x/ux.symfony.com/assets/vue/controllers/PackageSearch.js.
Backward Compatibility promise
This bundle aims at following the same Backward Compatibility promise as the Symfony framework: https://symfony.com/doc/current/contributing/code/bc.html