ngVue in FactSet
Using ngVue to create VueJS Components in an AngularJS 1.5 Codebase
Alexandru Olteanu
Marty Dimitrova
Thomas Truong
Agenda
- What is ngVue?
- How to use ngVue?
- Constants
- Broadcasting
- Vuex Store
- Translate
What is ngVue?
ngVue, is an Angular module that allows you to develop/use Vue components in AngularJS applications.
It can be used in the existing Angular applications and helps migrate the view parts of the application from Angular 1.x to Vue 2.
How to install it?
ngVue is an open source project found on https://github.com/ngVue/ngVue
yarn add ngVue
npm install ngVue
import 'ngVue';
angular.module('appName', ['ngVue']);
How to use ngVue?
The basic principle of ngVue is that you write Vue components and simply insert them in your Angular code.
Props
You can use the component in Angular templates like any normal directive.
<batman
v-props-forename="$ctrl.batman.forename"
v-props-surname="$ctrl.batman.surname">
</batman>
However, for the props you need to prefix with v-props-* or v-props for an object of all the prop attributes.
Events
Events can be handled from VueJS to AngularJS components by binding functions references as v-on-
<version
v-on-framework="$ctrl.update()">
</version>
It will be emitted on the Vue component side.
changeFramework() {
this.$emit('framework', this.currentFramework);
...
}
Two-Way Binding
VueJS doesn't support two-way binding, therefore in the Angular directive we will need to cater for this via props and events.
<version
v-props-framework="$ctrl.framework"
v-on-framework="$ctrl.update()">
</version>
In this example framework is passed down as one-way binding from the parent (container) to the component Version. The event framework is being used as data changes are being sent back to the callback function update().
Create Vue Component
We first use the createVueComponent factory to create usable Angular directive which is bound to a specific Vue component.
import app from '~ngAppModule';
import Vue from 'vue';
import Component from './Batman.vue';
app.directive('vueBatman', createVueComponent =>
createVueComponent(
Vue.component('Batman', Component)
)
);
Constants
Just like in AngularJS, using constants in templates in VueJS requires a bit of work.
Our recommended approach is utilising the capabilities of Vue - defining a constant plugin.
Using the $const Plugin
In order to add your constants to the plugin, all you need to do is register your plugin with a constants file.
Using them in a template is as easy as:
const definition: Record<string, string> = {
Robin1: 'Dick Grayson',
Robin2: 'Jason Todd',
Robin3: 'Tim Drake',
Robin4: 'Damien Wayne',
};
export default definition;
<strong>{{ $const('Robin1') }}</strong>
Broadcasting
Unlike AngularJS, VueJS components are designed to be very self-contained (plug-and-play) and have no relation to the parent unless passed in via a prop or through the store.
Event Handling in Parent
The ability to $emit is still available in VueJS components so if you're converting an AngularJS component with broadcasting logic. You can emit the responsibility to parent (most likely an Angular Component) for now.
Event Bus
import bus from './eventBus';
const eventBusPlugin = ($rootScope: any): void => {
bus.$on('ng:broadcast', (name: string, params: any) => {
$rootScope.$broadcast(name, params);
});
};
eventBusPlugin.$inject = ['$rootScope'];
export default eventBusPlugin;
import {eventBus} from '../../../plugins'
...
send() {
eventBus.$emit('ng:broadcast', 'like', this.framework);
}
In the event if you HAVE to broadcast from a Vue component, you can use an Event Bus plugin.
Vuex Store
State management pattern + library for Vue.js applications.
Centralised store for all the components in an application.
Has rules ensuring that the state can only be mutated in a predictable fashion.
How is AngularJS managing shared state?
All applications have one root scope.
All other scopes are descendants of the root scope.
Commonly components would access the root scope to modify state on the application level.
What is the single source of truth in an ngVue app?
The goal is to migrate everything to VueJS.
We can move the state into Vuex by migrating any shared states such as rootScope from Angular to Vuex.
Translate
We SHOULD be able to do the following:
However, this is not possible because the root of the app is Angular and not Vue.
<template>
<div>
{{ $vtranslate('welcomeMessage') }}
</div>
</template>
Translate Plugin
$vtranslate can be accessed from the template as such. The key 'welcomeMessage' is the key in the language file.
To solve this issue, we wrote a plugin that will inject translate into our Vue components globally.
ngVue utils
Team ATM wrote a library to register plugins for assisting the migration from Angular to Vue.
https://github.factset.com/FactSet/ng-vue-utils
Register
import ngAppModule from '~ngAppModule';
import Vue from 'vue';
import constants from './constants';
import {translate} from '../lang/en-US.messageformat.json';
import store from './components/vue/store';
import {registerNgVuePlugins} from '@fds/ng-vue-utils';
registerNgVuePlugins(ngAppModule, Vue, {
constants,
translate,
store
});
Resources
ngVue
By Thomas Truong
ngVue
ngVue in FactSet
- 79