Vue.js Running On Symfony4 and Creating Reusable Components

By | January 27, 2019

As i tell in my last 2 posts, i am developing a vocabulary web application. We have seen running Symfony4 on Docker Compose. In this post, we are going to add Vue.js into Symfony4. For this, we are going to install Webpack Encore and dependencies of Javascript. I have shared my informations of sources by links in the past.

Firstly, in order run these commands to install Webpack EncoreYarn as well as Composer should be installed your device.

composer require webpack-encore
yarn install

It will create webpack.config.js file and i have edited like this.

var Encore = require('@symfony/webpack-encore');

    // directory where compiled assets will be stored

    // the public path used by the web server to access the previous directory
    // only needed for CDN's or sub-directory deploy

     * Add 1 entry for each "page" of your app
     * (including one that's included on every page - e.g. "app")
     * Each entry will result in one JavaScript file (e.g. app.js)
     * and one CSS file (e.g. app.css) if you JavaScript imports CSS.
    // will create public/build/app.js and public/build/app.css
    .addEntry('dashboard', './assets/js/dashboard.js')

    // allow legacy applications to use $/jQuery as a global variable

    // enable source maps during development

    // empty the outputPath dir before each build

    // show OS notifications when builds finish/fail



module.exports = Encore.getWebpackConfig();

Then this configuration, we should install dependencies of Javascript. I am showing my package.json.

  "devDependencies": {
    "@symfony/webpack-encore": "^0.19.0",
    "less": "^3.8.1",
    "less-loader": "^4.1.0",
    "node-sass": "^4.9.3",
    "sass-loader": "^7.1.0",
    "vue": "^2.5.17",
    "vue-loader": "^14",
    "vue-template-compiler": "^2.5.17",
    "webpack-notifier": "^1.6.0"
  "license": "UNLICENSED",
  "private": true,
  "scripts": {
    "dev-server": "encore dev-server",
    "dev": "encore dev",
    "watch": "encore dev --watch",
    "build": "encore production"
  "dependencies": {
    "axios": "^0.18.0",
    "bootstrap": "^4.1.3",
    "font-awesome": "^4.7.0",
    "graceful-fs": "^4.1.11",
    "izitoast": "^1.4.0",
    "jquery": "2.2.4",
    "jquery-easing": "^0.0.1",
    "popper.js": "^1.14.4",
    "select2": "^4.0.6-rc.1",
    "vue-router": "^3.0.1"

Thus, you just run this command.

yarn install

Right now, we had Bootstrap 4, Vue.js 2, Vue-cli and a lot of packages that what we need.

From now on, we can start to create structure of Vue.js. I am creating assets/js/layout.js file. These lines mean that file.

'use strict';

const $ = require('jquery');
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
import 'jquery-easing';
import './sb-admin.min.js';
import '../css/sb-admin.min.css'

So, these lines are my needing libraries everywhere. Then, i will create assets/js/dashboard.js file. Like this.

'use strict';


import Vue from 'vue';

import Setting from '../components/user/Setting';
import Select2 from '../components/form_items/Select2';

new Vue({
    el: '#app-dashboard',
    components: {Select2,Setting}

This file will initialize our Vue.js project. Now, we will create our components. I need a Select2 component that i can use it everywhere. I had written a Select component into assets/components/form_items/Select2.vue.

    <select class="select2 col-3">
        <option v-for="(value, key) in option">{{ value + " (" + key + ")" }}</option>


    import 'select2';
    import 'select2/dist/css/select2.css';

    export default {
        name: "select2",
        props: {
            option: Object
        data() {
            return {}
        mounted: function () {
        methods: {},
        created: function () {

<style scoped>


With this way, we can pass option value from out. In Setting.vue file will send a XHR request with Axios library. Then, it is sending these values to Select2 component. First, i am showing Setting component.


        <div class="form-group">
            <label>Target language: </label>
            <select2 :option="optns"></select2>
        <button type="submit" class="btn btn-primary">Submit</button>

    import Select2 from '../form_items/Select2';
    import axios from 'axios';

    export default {
        components: {Select2},
        name: "setting",
        data() {
            return {
                optns: {}
        created() {
                .then(response => {
                    // JSON responses are automatically parsed.
                    this.optns =
                .catch(e => {
        methods: {}

<style scoped>


Well, from now on, we can create a Symfony controller in order that we will get the languages.

bin/console make:controller

After creating of controller, my controller is like this.


namespace App\Controller;

use Google\Cloud\Translate\TranslateClient;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;

 * Class GoogleTranslateApiController
 * @package App\Controller
class GoogleTranslateApiController extends AbstractController
     * @Route("/google/translate/api", name="google_translate_api")
    public function index()
        $translate = new TranslateClient();
        $targetLanguage = 'en';
        $result = $translate->localizedLanguages([
            'target' => $targetLanguage,

        $languages = array();
        foreach ($result as $lang) {
            $languages[$lang['code']] = $lang['name'];

        return new JsonResponse(
                'status' => true,
                'languages' => $languages
            ), 200);

Further all of these, we are using this command that to build by Webpack.

yarn encore dev --watch

This command will create 3 kind of files.

  • public/build/dashboard.css
  • public/build/dashboard.js
  • public/build/manifest.json

Right, we can load our Twig files. My user controller is like this.


namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

 * Class UserController
 * @package App\Controller
 * @Route("/user")
class UserController extends AbstractController
     * @Route("/setting", name="setting")
    public function index()
        return $this->render('user/setting.html.twig');

It just load Twig file and my twig file means that.

{% extends 'base.html.twig' %}

{% block head %}
{% endblock %}

{% block body %}
    <div id="app-dashboard">
{% endblock %}

{% block javascripts %}
    <script src="{{ asset('build/dashboard.js') }}" type="text/javascript"></script>
{% endblock %}

As you see, we are adding builded dashbard.js. And my base.html.twigmeans that.

<html lang="en">


    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>SB Admin - Dashboard</title>

    <link rel="stylesheet" href=""
          integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
    <!-- Bootstrap core CSS-->
    <link href="{{ asset('build/dashboard.css') }}" rel="stylesheet">

    {% block head %}{% endblock %}

<nav class="navbar navbar-expand navbar-dark bg-dark static-top">

    <a class="navbar-brand mr-1" href="index.html">Start Bootstrap</a>

    <button class="btn btn-link btn-sm text-white order-1 order-sm-0" id="sidebarToggle" href="#">
        <i class="fas fa-bars"></i>

    <!-- Navbar -->
    <ul class="navbar-nav ml-auto ml-md-0">
        <li class="nav-item dropdown no-arrow">


<div id="wrapper">

    <!-- Sidebar -->
    <ul class="sidebar navbar-nav">
        <li class="nav-item active">
            <a class="nav-link" href="index.html">
                <i class="fas fa-fw fa-tachometer-alt"></i>
        <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" id="pagesDropdown" role="button" data-toggle="dropdown"
               aria-haspopup="true" aria-expanded="false">
                <i class="fas fa-fw fa-folder"></i>
            <div class="dropdown-menu" aria-labelledby="pagesDropdown">
                <h6 class="dropdown-header">Login Screens:</h6>
                <a class="dropdown-item" href="login.html">Login</a>
                <a class="dropdown-item" href="register.html">Register</a>
        <li class="nav-item">
            <a class="nav-link" href="charts.html">
                <i class="fas fa-fw fa-chart-area"></i>

    <div id="content-wrapper">

        <div class="container-fluid">
            {% block body %}{% endblock %}

        <!-- Sticky Footer -->
        <footer class="sticky-footer">
            <div class="container my-auto">
                <div class="copyright text-center my-auto">
                    <span>Copyright © 2018</span>

    <!-- /.content-wrapper -->

{% block javascripts %}{% endblock %}

Right now, we are running this comand again.

yarn run encore dev --watch

Well, we have obtained this view.

As you see, from now on, we have had a Select 2 component that we can use it everywhere. We are passing values from root component. Here, our root component is Setting.Vue As well as, we can create that what we need any components with this way.