this is an experimental feature and still under development
What if I want to use Angular filters in Vue.js templates? Is it possible to use Vuex to manage the state? How can I reuse the business code in Vue.js when the application is too deep into Angular 1.x? ...
There are more complicated problems when we try to integrate Angular 1.x with Vue.js. It is impossible to solve them all
but it's important to provide flexibility for enhancement while keeping ngVue
small and simple. So we introduce a
new module ngVue.plugins
.
ngVue.plugins
is a UMD module and you can use it in AMD, CommonJS and browser globals.
Make sure that AngularJS 1.x, Vue.js and ngVue are loaded and then the plugins module. Register thees module as dependencies in your app: ngVue and ngVue.plugins:
import Angular from 'angular'
import Vue from 'vue'
import 'ngVue'
import 'ngVue/build/plugins.js'
angular.module('yourApp', ['ngVue', 'ngVue.plugins'])
ngVue.plugins
creates an Angular service $ngVue
. This service implements a plugins system and other functionality.
For the plugins, they will control the Vue instances with the lifecycle hooks, so you can use Vue.js plugins or use
Angular factories/services resolved by the inject service to Vue.js.
name | description |
---|---|
filters | (built-in) register Angular filters to Vue.js |
The provider $ngVue
has only one method install
to use a plugin during the configuration phase of Angular.
Arguments
callback
(Function
): the callback function receives the inject service$injector
and this service injects the provider instances only. The callback should return a plain object{$name[, $config, $vue, $plugin]}
:$name
(String): required to avoid name collisions in the provider, it is used as the namespace in the$ngVue
provider$config
(Object): optional, it contains the methods for users to set up the plugin and those methods will be exposed only to the namespace object created by$name
in the$ngVue
provider$vue
(Object): optional, it contains the lifecycle hooks of the Vue instances$plugin
(Object): optional, it contains the lifecycle hooks of the ngVue plugins
There are two types of lifecycle hooks:
type | hook name |
---|---|
ngVue plugins | init |
Vue instances | beforeCreated, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed |
For the ngVue plugin hook init
, it is invoked when the service $ngVue
is instantiated by the inject service. It is when you can add global-level functionality to Vue.js.
The Vue instance hooks will be invoked when any Vue instance in Angular application calls its own lifecycle hooks. You can subscribe those hooks to do anything with Angular services (it is not recommended to use Angular services in Vue components).
Those hooks share the same signature ($injector, Vue, context) => void
:
$injector
the injector service that can access to all the instantiated servicesVue
the base class of Vue instancescontext
only useful for the Vue instance hooks, the context points to the Vue instance invoking it
Require ngVue.plugins
and the plugin module. That's it :-)
angular.module('app', ['ngVue.plugins', 'custom.plugin'])
Each ngVue plugin has a namespace object (defined by the plugin's $name
) and all the configuration options are contained there
angular.module('app', ['ngVue.plugins', 'custom.plugin'])
.config(function($ngVueProvider) {
$ngVueProvider.namespace.configMethod()
})
Require the module ngVue.plugins
and then install the plugin in $ngVue
provider during the configuration phase:
angular.module('custom.plugin', ['ngVue.plugins'])
.config(function($ngVueProvider) {
$ngVueProvider.install(($injector) => {
// do something with other providers injected by `$injector`
return {
$name: 'namespace',
$config: { ...configMethod },
$plugin: { ...pluginHooks },
$vue: { ...vueHooks }
}
})
})
Vue.js cannot detect these changes on the scope objects while AngularJS can -- read about their differences in Caveats.
- dynamically add a new property to the reactive object:
vm.b = 'a'
- delete a property from the object:
delete vm.b
- set an array element with the index:
array[0] = newElement
- modify the length of the array:
array.length = 0
You have to mutate the scope object in a reactive way to trigger the view updates in Vue.js. You are likely to refactor all the controller code. So we introduce the quirk mode.
The quirk mode enables AngularJS to propagate all the watched changes to Vue.js and so you will not have to refactor any controller code to trigger the reactivity system to re-render the components.
You can activate it with $ngVueProvider
during the config phase:
angular.module('yourApp', ['ngVue', 'ngVue.plugins'])
.config(($ngVueProvider) => {
$ngVueProvider.activeQuirkMode()
})
Sometimes a plugin requires you to pass extra properties to the root Vue instance in order to access its features on
any child component. You can use $ngVueProvider
at a configuration phase of your Angular.js application to
pass such extra properties. This way you can inject Vuex's store
, Vue i18n's i18n
, or your own custom Vue.js
plugin object.
// app.js
import Vue from 'vue'
import myPlugin from './myPlugin'
Vue.use(myPlugin)
const myPluginFeature = new myPlugin.Feature()
angular.module('yourApp', ['ngVue', 'ngVue.plugins'])
.config(($ngVueProvider) => {
$ngVueProvider.setRootVueInstanceProps({
myPluginFeature: myPluginFeature
})
})
Note: Vue's instance lifecycle hooks will be discarded when passed through
$ngVueProvider.setRootVueInstanceProps()
as there is already a mechanism to handle lifecycle hooks
Vuex support is a bit opinionated and its implementation focuses on simplicity. You must use Vue.use(Vuex)
to enable automatic injection of the store into child components.
Then, import (or define) your Vuex.Store
instance and tell ngVue
to use it on all Vue instances created by it.
You can enabled it during the configuration phase of the Angular.js app, using $ngVueProvider.setRootVueInstanceProps()
:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
message: 'Hello from ngVue!'
}
})
// app.js
import store from './store'
angular.module('yourApp', ['ngVue', 'ngVue.plugins'])
.config(($ngVueProvider) => {
$ngVueProvider.setRootVueInstanceProps({
store: store
})
})
All components created by ngVue
will have access to this.$store
, as described in the
Vuex documentation