How to send data from PHP to Vue.js?

Use the method Media::addJsDef([]) to make your data available in the window context. If other modules can be present on the same, prefix your names with the module name to avoid name collision.

This is a convenient way to send the links Vue.js could call, generated by the router.

Example:

    Media::addJsDef([
        'myVueJsModuleRouteToSomeAction' => $this->context->link->getAdminLink(
            'AdminAjaxMyVueJsModule',
            true,
            [],
            [
                'action' => 'RouteToSomeAction',
                'ajax' => 1,
            ]
        ),
    ]);

How to send data from Symfony controller to Vue.js?

PHP controller:

namespace Module\YourModule\Controller\Admin;

use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;

class YourControllerNameController extends FrameworkBundleAdminController
{
    public function demoAction()
    {
        return $this->render('@Modules/yourmodule/views/templates/admin/demo.html.twig', [
            'yourModule' => [
                'keyA' => 'valueA',
                'keyB' => 'valueB',
            ]
        ]);
    }
}

Twig template:

{% extends '@PrestaShop/Admin/layout.html.twig' %}
{% trans_default_domain "Module.YourModule.Admin" %}

{% block stylesheets %}
  {# include some external stylesheets #}
  <link rel="stylesheet" href="https:/static.example.com/dummy/an-external-stylesheet-example.css" type="text/css" media="all">
  {# include some local stylesheets #}
  <link rel="stylesheet" href="{{ asset('../modules/yourmodule/views/css/app.css') }}" type="text/css" media="all">
{% endblock %}

{% block content %}
  <div id="app"></div>
{% endblock %}

{% block javascripts %}
    {{ parent() }}

    <script>
      var yourModule = {{ yourModule|json_encode|raw }}
    </script>

    {# include some external JavaScript #}
    <script src="https://static.example.com/dummy/an-external-javascript-example.js"></script>
    
    {# include some local JavaScript #}
    <script src="{{ asset('../modules/your-module/views/js/chunk-vendors.js') }}" async defer></script>
    <script src="{{ asset('../modules/your-module/views/js/app.js') }}" async defer></script>
{% endblock %}

Use it in JavaScript, i.e. in your Vue Store:

const { yourModule } = window;
const { keyA, keyB } = yourModule;

export default {
    state: {
        keyA,
        keyB,
        yourModule
    },
    getters: {
        keyA: (state) => state.keyA,
        keyB: (state) => state.keyB,
        yourModule: (state) => state.yourModule,
    }
}

How to run several Vue.js applications on the same page

The only thing to consider is the div ID you want to hook your application on.

By default, Vue.js creates your application with a <div id="app"></div>. To avoid it colliding with other applications or modules, replace references to this ID in the template and JS development files with something more specific.

For instance, app => yourModuleNameApp.

I want to add another version of Bootstrap / PrestaShop UI-Kit of my application in the Back-office, how to avoid conflicts with the one provided by PrestaShop?

Bootstrap needs to be disabled on the module content. To do so:

  • Set the bootstrap property of the module as false
  • Load this piece of CSS for users with multi shop:
<style>
  /** Hide native multistore module activation panel, because of visual regressions on non-bootstrap content */
  #content.nobootstrap div.bootstrap.panel {
    display: none;
  }
</style>