Vue is a JavaScript application framework similar to Angular and React, but considerably lighter. Despite its tiny footprint, Vue is a powerful and flexible framework. Wijmo's library of JavaScript UI Components is also compact, robust, and flexible. The two libraries are a great match.
Wijmo features over 40 locales, referred to as cultures, and 25 different built-in themes. By default, Wijmo formats and parses data using the American English culture. If your application targets other cultures, include references to the appropriate Wijmo culture files.
Below we'll create a sample Vue application with Wijmo controls. Then we will outline how to change Wijmo themes and cultures in a Vue application using both static and dynamic methods.
Use Vue CLI to create a project with default settings:
vue create wijmo-sample
cd wijmo-sample
Details about creating a Vue CLI application creation can be found here.
Add Wijmo to the project:
yarn add @grapecity/wijmo.vue2.all
export const countries = [
'US',
'Germany',
'UK',
'Japan',
'Italy',
'Greece',
];
export const data = [];
for (let i = 0; i < countries.length; i++) {
data.push({
country: countries[i],
downloads: Math.round(Math.random() * 20000),
sales: Math.random() * 10000,
expenses: Math.random() * 5000
})
}
<template>
<div class="wijmo-sample">
<h1>Wijmo controls sample</h1>
<p>
<strong>ComboBox:</strong><br />
<wj-combo-box :itemsSource="countries" />
</p>
<p>
<strong>InputNumber:</strong><br />
<wj-input-number :value="1234.5678" :step="1" />
</p>
<p>
<strong>InputDate:</strong><br />
<wj-input-date />
</p>
<p>
<strong>Calendar:</strong><br />
<wj-calendar />
</p>
<p>
<strong>FlexGrid:</strong><br />
<wj-flex-grid :itemsSource="data">
<wj-flex-grid-column binding="country" header="Country" />
<wj-flex-grid-column binding="downloads" header="Downloads" />
<wj-flex-grid-column binding="sales" header="Sales" format="c0" />
<wj-flex-grid-column binding="expenses" header="Expenses" format="c0"
/>
</wj-flex-grid>
</p>
</div><
</template>
<script>
import * as dataSource from '../data';
import "@grapecity/wijmo.styles/wijmo.css";
import "@grapecity/wijmo.vue2.input";
import "@grapecity/wijmo.vue2.grid";
export default {
name: 'WijmoSample',
data: function () {
return {
data: dataSource.data,
countries: dataSource.countries,
};
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.wijmo-sample {
width: 50em;
margin: 3em auto;
}
.wj-calendar {
width: 25em;
}
</style>
<template>
<div id="app">
<WijmoSample />
</div>
</template>
<script>
import WijmoSample from './components/WijmoSample.vue'
export default {
name: 'App',
components: {
WijmoSample,
}
}
</script>
Remove unused "src/assets" folder and "src/components/HelloWorld.vue" file
Run the sample application.
yarn serve
Use this sample application as a base for the demonstration of static and dynamic methods.
Import the required css or js files to statically use a built-in theme or locale.
Built-in themes are located in themes folder of @grapecity/wijmo.styles module.
// replace this line
// import "@grapecity/wijmo.styles/wijmo.css";
// by
import "@grapecity/wijmo.styles/themes/wijmo.theme.organic.css";
Built-in locales are located in @grapecity/wijmo.cultures
module.
// import Japanese locale
import "@grapecity/wijmo.cultures/wijmo.culture.ja";
As a result <script> import"
part of _src/components/WijmoSample.vue
file looks like:
<script>
import * as dataSource from '../data';
import "@grapecity/wijmo.styles/themes/wijmo.theme.organic.css";
import "@grapecity/wijmo.vue2.input";
import "@grapecity/wijmo.vue2.grid";
import "@grapecity/wijmo.cultures/wijmo.culture.ja";
export default {
name: 'WijmoSample',
data: function () {
return {
data: dataSource.data,
countries: dataSource.countries,
};
}
}
</script>
Here's what the application should look:
Dynamic theming and localization require:
The most efficient resource publication method is webpack configuration of Vue project. We configure webpack to achieve next objectives:
To achieve these objectives, we create vue.config.js file in the root of the project with the content:
const path = require('path');
const glob = require('glob');
// public folder name for wijmo themes styles
const wijmoThemesPublicFolder = 'themes';
// public folder name for wijmo cultures
const wijmoCulturesPublicFolder = 'cultures';
// resources source folders
const wijmoThemesSrcFolder = path.resolve('./node_modules/@grapecity/wijmo.styles/themes');
const wijmoCulturesSrcFolder = path.resolve('./node_modules/@grapecity/wijmo.cultures');
// list of available themes
const themes = glob
.sync('wijmo.theme.*.css', { cwd: wijmoThemesSrcFolder })
.map(file => file.replace(/^wijmo\.theme\.(.+)\.css$/, '$1'))
.sort();
themes.unshift('default');
// list of available cultures
const cultures = glob
.sync('wijmo.culture.*.js', { cwd: wijmoCulturesSrcFolder })
.map(file => file.replace(/^wijmo\.culture\.(.+)\.js$/, '$1'))
.sort();
module.exports = {
chainWebpack: config => {
// configure DefinePlugin
config.plugin('define').tap(definitions => {
// define process.env variables to use in application at runtime
const env = definitions[0]['process.env'];
env.WIJMO_THEMES_PUBLIC_FOLDER = JSON.stringify(wijmoThemesPublicFolder);
env.WIJMO_CULTURES_PUBLIC_FOLDER = JSON.stringify(wijmoCulturesPublicFolder);
env.WIJMO_THEMES = JSON.stringify(themes);
env.WIJMO_CULTURES = JSON.stringify(cultures);
return definitions;
});
// configure CopyWebpackPlugin
config.plugin('copy').tap(args => {
// copy wijmo themes
args[0].push({
context: wijmoThemesSrcFolder,
from: '*.css',
to: path.resolve('./dist/' + wijmoThemesPublicFolder),
});
// copy wijmo cultures
args[0].push({
context: wijmoCulturesSrcFolder,
from: '*.js',
to: path.resolve('./dist/' + wijmoCulturesPublicFolder),
});
return args;
})
}
}
Dynamically add one of these elements (<link>
for css, <script>
for js) to HTML in the document head as follows:
<link type="text/css" rel="stylesheet" href="public-path-to-css-file" id="css-resourse-id" />
<script type="text/javascript" src="public-path-to-js-file" id="js-resourse-id"></script>
Loading a theme or locale requires an extra step to re-render the Wijmo controls. Re-render by using the invalidateAll static method of the Control Wijmo base class. The invalidateAll method should be called in the onload event of the added <link>
or <script>
element.
To simplify the manipulation of the elements, we create a universal function that handles the removal of the previous element and adds the new one.
Use this function as the WijmoSample component method:
addResource: function (resourceId, resourceLocation, isCulture) {
// remove previously applied resource
let element = document.getElementById(resourceId);
if (element) {
element.parentNode.removeChild(element);
}
// add element
if (resourceLocation) {
let element = null;
const publicPath = process.env.BASE_URL; // publicPath of app (https://cli.vuejs.org/guide/html-and-static-assets.html#the-public-folder)
if (isCulture) { // script
element = document.createElement('script');
element.type = 'text/javascript';
element.src = publicPath + resourceLocation;<
} else { // styleseet
element = document.createElement('link');
element.type = 'text/css';
element.rel = 'stylesheet';
element.href = publicPath + resourceLocation;
}
element.id = resourceId;
element.onload = () => {
// refresh all controls on page
Control.invalidateAll();
};
document.head.appendChild(element);
}
}
We use "_process.env.BASE_URL"_ value for cases when deploying the application in a non-root folder of the webserver.
Now resources may be loaded by calling "this.addResource" method:
// load theme css
this.addResource('theme-element-id', 'public-path-to-theme-css');
// load locale js
this.addResource('js-element-id', 'public-path-to-locale-js', true);
Names of public folders of themes and locales resources are accessable in _process.env.WIJMO_THEMES_PUBLIC_FOLDER_ and _process.env.WIJMO_CULTURES_PUBLIC_FOLDER_ variables, respectively (in accordance with the earlier defined webpack configuration in vue.config.js file).
Finally, we add two Wijmo ComboBoxes from which we select a theme and locale. Take the items for selectors from the "process.env" variable (see "vue.config.js" file). Event handlers apply default values for theme and locale to each selector.
The resulting WijmoSample code ("src/components/WijmoSample.vue" file) should look like:
<template>
<div class="wijmo-sample">
<h1>Wijmo controls sample</h1>
<hr />
<h2>Settings</h2>
<p>
<strong>Theme:</strong>
<wj-combo-box
:itemsSource="themes"
:initialized="themeComboboxInitialized"
:selectedIndexChanged="themeChanged"
/>
<br />
<br />
<strong>Culture:</strong>
<wj-combo-box
:itemsSource="cultures"
:initialized="cultureComboboxInitialized"
:selectedIndexChanged="cultureChanged"
/>
</p>
<hr />
<p>
<strong>ComboBox:</strong><br />
<wj-combo-box :itemsSource="countries" />
</p>
<p>
<strong>InputNumber:</strong><br /><
<wj-input-number :value="1234.5678" :step="1" />
</p>
<p>
<strong>InputDate:</strong><br />
<wj-input-date />
</p>
<p>
<strong>Calendar:</strong><br />
<wj-calendar />
</p>
<p>
<strong>FlexGrid:</strong><br />
<wj-flex-grid :itemsSource="data">
<wj-flex-grid-column binding="country" header="Country" />
<wj-flex-grid-column binding="downloads" header="Downloads" />
<wj-flex-grid-column binding="sales" header="Sales" format="c0" />
<wj-flex-grid-column binding="expenses" header="Expenses" format="c0"
/>
</wj-flex-grid>
</p>
</div>
</template>
<script>
import * as dataSource from '../data';
import "@grapecity/wijmo.styles/wijmo.css";
import "@grapecity/wijmo.vue2.input";
import "@grapecity/wijmo.vue2.grid";
import { Control } from "@grapecity/wijmo";
export default {
name: 'WijmoSample',
data: function () {
return {
data: dataSource.data,
countries: dataSource.countries,
// defined in vue.config.js
themes: process.env.WIJMO_THEMES,
cultures: process.env.WIJMO_CULTURES,
// initial values
defaultTheme: 'default',
defaultCulture: 'en',
};
},
methods: {
themeComboboxInitialized: function (combobox) {
// apply default theme
combobox.selectedValue = this.defaultTheme;
this.themeChanged(combobox);
},
themeChanged: function (combobox) {
// load theme css<
const themeStyleId = 'wijmo-theme';
const themeLocation = process.env.WIJMO_THEMES_PUBLIC_FOLDER // wijmo cultures public path (defined in vue.config.js)
+ '/wijmo.theme.' + combobox.selectedValue + '.css';
this.addResource(themeStyleId, combobox.selectedIndex && themeLocation);<
},
cultureComboboxInitialized: function (combobox) {<
// apply default culture
combobox.selectedValue = this.defaultCulture;
this.cultureChanged(combobox);
},
cultureChanged: function (combobox) {
const scriptCultureId = 'wijmo-culture';
const cultureLocation = process.env.WIJMO_CULTURES_PUBLIC_FOLDER // wijmo cultures public path (defined in vue.config.js)
+ '/wijmo.culture.' + combobox.selectedValue + '.js';
this.addResource(scriptCultureId, cultureLocation, true);
},
addResource: function (resourceId, resourceLocation, isCulture) {
// remove previously applied resource<
let element = document.getElementById(resourceId);
if (element) {
element.parentNode.removeChild(element);
}
// add element
if (resourceLocation) {
let element = null;
const publicPath = process.env.BASE_URL; // publicPath of app (https://cli.vuejs.org/guide/html-and-static-assets.html#the-public-folder)
if (isCulture) { // script
element = document.createElement('script');
element.type = 'text/javascript';
element.src = publicPath + resourceLocation;<
} else { // styleseet
element = document.createElement('link');
element.type = 'text/css';
element.rel = 'stylesheet';
element.href = publicPath + resourceLocation;
}
element.id = resourceId;
element.onload = () => {
// refresh all controls on page
Control.invalidateAll();
};
document.head.appendChild(element);
}
},
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.wijmo-sample {
width: 50em;<
margin: 3em auto;
}
.wj-calendar {
width: 25em;
}
</style>
The resulting application:
The application theme or locale changes with every change of the corresponding selector value.
Thank you for reading. Let us know how this information helps with your applications.
Read more about creating a Vue project.
Theming and localization of a Vue application based on Wijmo components are both rather simple. There are two methods for applying of build-in themes and locales: static and dynamic.
A static method is straightforward and maybe applicable when the required theme and locale are both known in advance.
The dynamic method is more complicated but permits the creation of applications that can change its appearance and culture-dependent formatting on the fly.
Happy coding! If you have questions or comments be sure to enter them below.