Concrete5 + Vue CLI3: Making Rich UI in package. 1st: Set up vue project on Concrete5 package.
技術スタック Concrete5JavascriptVue.js

Concrete5 + Vue CLI3: Making Rich UI in package. 1st: Set up vue project on Concrete5 package.


Hello everyone. In this post, I explain how to use Vue.js to make rich UI in Concrete5 package. At there, I write the process that create vue project in C5 package directory and use compiled js file.

I assumed Readers know how to customize C5 packages and basic C5 knowledge.The C5’s version is 8.4+ in this post.

Why use Vue.js?

Reason is simple. Because making rich UI with PHP(C5 system) and jquery is so hard. C5 prepares helper to print form as below.

// Read Helper
$form = Core::make('helper/form');

//input type of text
echo $form->text($name, $default_value);

//text area
echo $form-> textarea($name, $default_value);

// File manager
$file_selector = Core::make('helper/concrete/file_manager');
echo $file_selector->file('label', 'name_attr', 'Select Photo', $default_fileObj);

When I write them on page view.php, forms are shown as below.

Input text, textarea and C5’s file manager appeared. These has name property and can post data.

Simply forms are enough to use them. But,

  • Implication of front-end validation
  • Repeatable form
  • Dependency Forms (There are some patterns correspond to inputed value)

These implication is hard with only jquery and PHP.

Let’s use vue.js power

Many Rich Form’s UI are developed easily with Vue.js, React.js and backbone.js( which manage data state and HTML template by javascript.) Using those libraries, we can develop rich UI while reducing the number of development days.

Preparation of creating package

Create a dedicated directory for package

Let’s make package has UI built by vue. Create custom package directory named ‘vuetest’ under /package . Directory structure as below.

documentroot $ cd ./package
package $ mkdir vuetest && touch ...
package $ tree vuetest
└── vuetest
    ├── controller.php
    ├── controllers
    │   └── single_page
    │       └── dashboard
    │           └── vuetest.php
    ├── db.xml
    ├── icon.png
    ├── js
    └── single_pages
        └── dashboard
            └── vuetest
                └── view.php

Create Vue project

Under package/vuetest, there are package controller file, single page file that shows UI. Then let’s create js directory and make vue project there, named as ‘packageui’.

package $ cd vuetest/js
js $ vue create packageui

Vue CLI v4.4.6
? Please pick a preset: default (babel, eslint) #default

Vue CLI v4.4.6
✨  Creating project in documentroot/vuetest/js/packageui.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while... 

🎉  Successfully created project packageui.

js $ cd packageui && tree -L 1
├── babel.config.js
├── node_modules
├── package-lock.json
├── package.json
├── public

Vue project has been created successfully! Next, create vue.config.js and write webpack setting for C5’s asset system.

packageui $ touch vue.config.js
module.exports = {
    configureWebpack: {
      output: {
        filename: '[name].js',
        chunkFilename: '[name].js'

This file configs that the name of compiled js files from vue file when running npm run build will be same name under the /dist directory.

When we build vue file on initial webpack config, built js file has been had hashed letters such as app384#34a.js . The hash will change at every build. Compiled js file name must be always same to be read by C5’s asset system. So I config that file.

If you want use vue project by multiple packages

In this time, I create dedicated vue project under the package called vuetest and its directory. But if you use it by multi packages, create /js directory under /application directory and make vue project under /application/js

Combine C5 and compiled js file

When running build with vue cli, compiled js file will be generated under /dist directory. Let’s config as C5 system and page renders components can read that files!

By the way, build main.js . That file renders App component at page contains div element with id attribute named as ‘app’.

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
packageui $ npm run build
├── babel.config.js
├── dist
│   ├── app.js
│   ├──
│   ├── chunk-vendors.js
│   ├──
│   ├── css
│   ├── favicon.ico
│   ├── img
│   └── index.html

Build succeeded. Some files are not needed, but it is just ok to config as reading app.js and chunk-vendor.js

To read those js files, write some PHP script in package’s install controller php file (package/vuetest/controller.php)

namespace Concrete\Package\Vuetest;
defined('C5_EXECUTE') or die('Access Denied.');
use \Concrete\Core\Asset\AssetList;
use \Concrete\Core\Asset\Asset;

class Controller extends \Concrete\Core\Package\Package {
    protected $pkgHandle = 'vuetest';
    protected $appVersionRequired = '5.7.4';
    protected $pkgVersion = '1.0.0';

    public function on_start()
        $al = AssetList::getInstance();
            'javascript', 'package-vue-build', 'js/packageui/dist/app.js',
            array('version' => '1.0.0', 'position' => Asset::ASSET_POSITION_FOOTER, 'combine' => true),
            'javascript', 'package-vue-chunk', 'js/packageui/dist/chunk-vendors.js',
            array('version' => '1.0.0', 'position' => Asset::ASSET_POSITION_FOOTER, 'combine' => true),
        $al->registerGroup('package-vue-production', array(
            array('javascript', 'package-vue-build'),
            array('javascript', 'package-vue-chunk'),

$al->register registers those two js files referred by path at controller of vuetest package. For simply asset reading, let’s group two files as name of package-vue-production .

C5 has asset registering/reading system like this. Using this system, we can use registered files anywhere pages without file path problem. Now, we have registered js files, so next we set reading them on the page.

Write PHP script in vuetest/single_pages/dashboard/vuetest/view.php as below

namespace Concrete\Package\Vuetest\Controller\SinglePage\Dashboard;
defined('C5_EXECUTE') or die('Access Denied.');
use \Concrete\Core\Page\Controller\DashboardPageController;

class Vuetest extends DashboardPageController
    public $packageHandle = 'vuetest';

    public function view() {
        $this->set('success', 'My success message');

$this->requireAsset('package-vue-production'); orders page controller that ‘Read registered asset name as “package-vue-production” on this page(view.php)!‘

After setting, let’s search if the js files are read. Opening Chrome developer tool…

Path /packages/vuetest/js/dist/** are found! Next, create div element has id="app" and see the page again.


defined('C5_EXECUTE') or die('Access Denied.');

<div id="app"></div>

Reload page…

Vue component (App) are rendered successfully!! Some image and layout dose not work because the paths for img and css are incorrect. But created vue component itself with vue CLI are read and appeared on target page.

Next Step

The above is the method to create a vue project on the concrete5 package and combine them. Setting to use vue has been readied, so next step, we create form to input data ,flow to register data in DB and registered data editing page .



Copyright © 2021 jun. All rights reserved.