Using ngVue to create VueJS Components in an AngularJS 1.5 Codebase
Alexandru Olteanu
Marty Dimitrova
Thomas Truong
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.
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']);
The basic principle of ngVue is that you write Vue components and simply insert them in your Angular code.
You can us 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-* for each attribute or v-props for an object of all the attributes.
Events can be handled from Vue to AngularJS componets 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);
...
}
Just like how VueJS doesn't support two-way binding we will need to do the same for ngVue components.
<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 also used as data changes being sent back to the callback update().
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)
)
);
Just like in Angular, using constants in templates in Vue requires a little bit of work.
Our recommended approach is utilising the capabilities of Vue - defining a constant 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 now 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>
Unlike Angular, Vue 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.
The ability to $emit is still available in Vue components so if you're converting an AngularJS component with broadcasting logic. You can emit the responsibility to parent (most likely Angular Component) for now.
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.
State management pattern + library for Vue.js applications
Centralized store for all the components in an application
Has rules ensuring that the state can only be mutated in a predictable fashion
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
The goal is to migrate everything to Vue
We can move state into Vuex while migrating
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
options: {
reveal: false,
}
},
actions: {
setReveal({commit}, show) {
commit('setReveal', show);
},
},
mutations: {
setReveal({options}, show) {
options.reveal = show;
},
},
getters: {
reveal: ({options: {reveal}}) => reveal,
},
});
From Web Build Tools we should be able to do the following:
That is not possible because the root of the app is Angular, not a Vue component.
To solve this issue, we wrote a plugin that will inject translate into our Vue components.
It works in the same way as mapGetters from Vuex
<template>
<div>
{{ $vtranslate('welcomeMessage') }}
</div>
</template>
$vtranslate is available globally and can be accessed from the template as such. The key 'welcomeMessage' is the key in the language file.