Combine Twig and Vue
Intro | Part 1: Passing down a vue object | Part 2: VueStorage | Part 3: Dynamic components | Part 4: v-models in your Symfony form | Part 5: fetching dynamic components
Part 1: Passing down a vue object
app.js
After installing webpack, the /assets/js/app.js should’ve been created for you.
To enable vue, you only need something like below:
// assets/js/app.js
import '../css/app.css'; // replace '.css with '.scss' if you're using sass.
import Vue from 'vue';
new Vue({
el: '#app',
delimiters: ['@{', '}'], // Twig already uses '{{' and '}}' delimiters, so here we specify an alternative.
})
This will apply vue to the element that has id="app" set, which you could use anywhere
inside your twig code.
We want to retrieve data from Twig. To achieve this let’s accept a global vue object.
Also, we might not need Vue in all pages, so we may want to only initialize it when
we actually provide the global vue object. Let’s update our code accordingly:
import '../css/app.css'; // replace '.css with '.scss' if you're using sass.
// Only import & load vue if the 'vue' var is set and is an object, so that other pages have smalled js files to load.
if (typeof vue === 'object') {
(async () => {
const VueImport = await import('vue');
const Vue = VueImport.default;
new Vue(Object.assign({
el: '#app',
delimiters: ['@{', '}'], // Twig already uses '{{' and '}}' delimiters, so here we specify an alternative.
}, vue));
})();
}
base.html.twig
Have your file look like below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
</head>
<body>
<div id="app">
{% block body %}{% endblock %}
</div>
{% block javascripts %}
{% block script %}{% endblock %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</body>
</html>
This is just a bare base example that makes sure your assets are loaded.
Here we put the body inside a div with ‘app’ to make sure that the app-element
is available to all pages.
Additionally, a script block is added inside javascript to be used in
other twig files.
Example dashboard page
Now let’s create a page that uses twig.
Run php bin/console make:controller Dashboard to
create a Dashboard controller with templates/dashboard/index.html.twig file and
replace the content of this index.html.twig file with the following:
{% extends 'base.html.twig' %}
{% block body %}
<p>
@{ seconds } seconds have past since you've loaded this page.
</p>
<p v-if="seconds > 5">
More than 5 seconds have past.
</p>
{% endblock %}
{% block script %}
<script>
vue = {
data: () => ({
seconds: 0,
}),
created() {
setInterval(() => { this.seconds++; }, 1000);
},
};
</script>
{% endblock %}
In this file the vue object can contain all the logic your
vue-instance needs. You can put general stuff like delimiters in your app.js, but if
you ever need you can overwrite it in this object.
Since twig holds server-side data you can put any data here in this object, making it available to your vue-instance.
Tip: By renaming your
index.html.twigtoindex.vue.twigIDE’s like PhpStorm will have better autocompletion for vue-components.