Open Aston13 opened 1 year ago
I'll look into adding this as it's definitely a common enough use case. However, you should be able to work around this in the meantime by creating your own custom ngVue plugins (oof looking at the docs I clearly need to update them).
import angular from "angular";
import { useNgVue, useNgVuePlugins, NgVueProvider } from "@jaredmcateer/ngvue3";
import { App } from "vue";
import PrimeVue from 'primevue/config';
angular.module("myModule", [useNgVue(), useNgVuePlugin()])
// ...
.config(($ngVueProvider: NgVueProvider) => {
$ngVueProvider.installNgVuePlugin(() => ({
$name: "ngVuePrimeVue",
$plugin: (_$injector: ng.auto.IInjectorService, app: App<any>) => {
app.use(PrimeVue, { unstyled: true });
}
}));
});
Just for additional reference since the docs are inaccurate right now.
export type PluginHook = ($injector: ng.auto.IInjectorService, app: App<Element>) => void;
export interface NgVuePlugin {
/** Plugin name */
$name: string;
/** Plugin install function */
$plugin: PluginHook;
/**
* Methods/properties to expose on the angular side as part
* of the ngVueProvider.plugins.<$name>.<$config.key>
*/
$config: Record<string, unknown>;
}
/**
* Installs an ngVue plugin, this gives access to configuration via the
* ngVueProvider and gives the Vue plugin install method access to the angular
* injector.
*
* @param plugin a function that returns a ngVue plugin config
* @member NgVueProvider
*/
installNgVuePlugin(plugin: () => NgVuePlugin) {
const { $name, $config, $plugin } = plugin();
this.pluginHooks.push($plugin);
this.pluginConfig[$name] = $config;
}
Just wanted to say thanks for the fast response! I went for this in the end with your help.
...
import NgVueModules, { type NgVuePlugin } from './NgVueModules';
import PrimeVue, { PrimeVueConfiguration } from 'primevue/config';
const primeVueConfig: PrimeVueConfiguration = { unstyled: false, pt: Bootstrap_PT, ripple: true };
const ngVueInjectables: NgVuePlugin[] = [
{ injectable: i18n },
{ injectable: HighchartsVue },
{ injectable: PrimeVue, context: { name: "ngVuePrimeVue", config: primeVueConfig }}
];
NgVueModules.create(angular, ngVueInjectables).registerComponents()
...
...
export type NgVuePlugin = {
injectable: any;
context?: {
name: string;
config: any;
}
}
export default class NgVueModules {
angularInstance: IAngularStatic;
vuePlugins?: NgVuePlugin[];
private constructor(angularInstance: IAngularStatic, vuePlugins?: NgVuePlugin[]) {
this.angularInstance = angularInstance;
this.vuePlugins = vuePlugins;
}
static create(angularInstance: IAngularStatic, vuePlugins?: NgVuePlugin[]): NgVueModules {
return new NgVueModules(angularInstance, vuePlugins);
}
registerComponents() {
this.angularInstance // Angular module that uses the ngVue3 lib to enable the usage of Vue 3 components in Angular 1.x.
.module('vue.components', [
useNgVue(),
useNgVuePlugins()
])
.config(['$ngVueProvider', ($ngVueProvider: NgVueProvider) => { // Syntax supports minimisation of $ngVueProvider
if(this.vuePlugins){
// Pass through for native Vue Plugins to the app instance.
this.vuePlugins.forEach(vuePlugin => {
if(vuePlugin.context){
$ngVueProvider.installNgVuePlugin(() => ({
$name: vuePlugin.context.name,
$plugin: (_$injector/*: ng.auto.IInjectorService */, app: App<any>) => {
app.use(vuePlugin.injectable, vuePlugin.context.config);
},
$config: {}
}))
} else {
$ngVueProvider.use(vuePlugin.injectable);
}
})
$ngVueProvider.component('valueType', <unknown>ValueType as Component)
}
}])
...
Leaving this here to potentially help others:
I had some "fun" getting Pinia working as a plugin.
Setting it up with the ngvue3 example apps was a breeze. Call app.use(createPinia())
as the $plugin function, and use I can use a store as per usual. i.e. const.store = useXyzStore();
in the vue component.
However, in my large angularjs app, this didn't work. The vue component couldn't find the root store (no active pinia) so it threw an exception (see this code here)
I haven't been able to track down the root cause, but I suspect either the injection context is being rewritten or the Symbol used with the provide/inject approach is no longer aligned.
My work around (for now) is as follows.
//in the angularjs app
.config(($ngVueProvider) => {
$ngVueProvider.installNgVuePlugin(() => ({
$name: "pinia",
$plugin: (_$injector, app) => {
const pinia = createPinia();
app.use(pinia);
//add the rootStore to the injection context.
app.provide('piniaInstance', pinia);
}
}))
})
and when a vue component needs to use a store, inject the rootStore instance.
import { inject } from 'vue';
const store = useXyzStore(inject('piniaInstance'));
This seem eerily similar to a problem people are also having on the other version of ngVue, https://github.com/ngVue/ngVue/issues/158, and $store
being missing. It would be super helpful if we could get a minimal reproducible example.
you can check this solution
Hi,
Firstly, I would just like to say that I am very appreciative of this library, it has enabled me to upgrade very smoothly from Vue 2 to Vue 3.
I have found a issue when trying to register a plugin that has a second options argument.
Vue's app.use function (
interface App<HostElement = any>
) has some overloads for passing options.However, I can't see how to do this in ngVue3 as there is only 1 argument for the use function. For example with PrimeVue: