Closed jens-morten-mikkelsen closed 1 year ago
👀
Bit of extra info here :)
The setup isn't a regular vue setup ^^'
Our vue lives within an angular app, since its a customer project, that needs IE11 support, and sadly was made in angular 1 🙄
Without spilling too much, i can say that basically we do not have a normal new Vue({...}).mount()
but instead we technically mount a new root Vue component when ever a vue component is placed within the angular app :)
The weird part for me is that it just stopped working when upgrading to 2.7, but i will try and see if a setup where we still use vue-demi but our vue version is bumped to 2.7 will work.
I will keep this issue updated with my findings, and will happily answer any questions and test potential theories :)
Update: TLDR - still not working.
I have tried the ways i have found for installing/using the plugin, but so far nothing worked. Tried using vue-demi (no dice) Tried different ways of instantiating Vue (createApp, new Vue() and nothing like it was before the update to 2.7) Tried installing and using vue-query where our different "ng-vue components" are defined.
I will here provide main.ts
and registerVueComponents.ts
files. If any other files could be usefull, just ask and i shall provide what i can :)
main.ts:
import Vue from "vue";
import TranslatePlugin from "./core/plugins/translate";
import PortalVue from "portal-vue";
import { config as configureComponents } from "./core/components/componentRegistry";
import { VueQueryPlugin } from "vue-query";
import { setupAngularRegistrations } from "./angular-registration";
import "./styling/main.css";
import { configCookies } from "@/core/cookies/cookieService";
Vue.use(TranslatePlugin);
Vue.use(PortalVue);
Vue.use(VueQueryPlugin);
configureComponents();
configCookies();
setupAngularRegistrations();
registerVueComponents:
import angular from "angular";
import Vue, { VueConstructor } from "vue";
import { Vue as VueInstance, CombinedVueInstance } from "vue/types/vue";
type VueComponentInstance = CombinedVueInstance<Vue, object, object, object, Record<never, any>>;
interface VueConstructorInternals extends VueConstructor
{
options: VueInstance["$options"];
}
export const registerVueComponent = (module: angular.IModule, name: string, component: any, hasNgSlot?: boolean) => {
component = Vue.extend(component); //<-- Tried .use(VueQueryPlugin) and VueQueryPlugin.install() here.
// Get vue component props or use manually passed props (from compositionApi component)
const propsList = Object.keys((component as VueConstructorInternals).options?.props || {});
// convert vue props to angular props
const scope = propsList.reduce((obj, key) => {
obj[ key ] = "<"; return obj;
}, {} as Record<string, string>);
// register angular component
module.directive(name, () => ({
restrict: "E",
scope,
link: (scope: angular.IScope, element: JQLite) => {
const targetNode = document.createElement("div");
element[ 0 ].classList.add("vue-universe");
element[ 0 ].appendChild(targetNode);
const cInstance = new component({
propsData: scope
});
cInstance.$mount(targetNode);
if (hasNgSlot) {
const ngContentSlot = cInstance.$el.querySelector("[data-ngslot=\"content\"]");
if (ngContentSlot && ngContentSlot.parentNode) {
ngContentSlot.parentNode.replaceChild(element[ 0 ].children[ 0 ], ngContentSlot);
} else {
console.error("data-ng-slot=\"content\", is not present on the component");
}
}
// watch angular props and rebind to vue instance
syncScopeChangesToProps(propsList, scope, cInstance);
cleanupOnDestroy(scope, cInstance, targetNode);
}
}));
};
function syncScopeChangesToProps(propsList: string[], scope: angular.IScope, cInstance: VueComponentInstance) {
for (const propName of propsList) {
scope.$watch(propName, (value) => {
setPropValueFromAngular(cInstance, propName, value);
});
}
}
function cleanupOnDestroy(scope: angular.IScope, cInstance: VueComponentInstance, element: HTMLElement) {
scope.$on("$destroy", () => {
cInstance.$destroy();
element.parentElement?.removeChild(element);
});
}
function setPropValueFromAngular(cInstance: VueComponentInstance, propName: string, value: unknown) {
/*
* If a prop value is set from angular, it is set as the prop value.
* This is only done to preserve the option to have default values for props on components that needs to be accessed from angular.
* */
cInstance.$props[ propName ] = value;
}
also package.json:
{
"name": "modern",
"version": "1.0.0",
"main": "index.js",
"license": "UNLICENSED",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build --emptyOutDir",
"build:watch": "vite build --mode watch --watch",
"start-all": "concurrently --kill-others \"npm run dev\" \"npm run build:watch\"",
"lint": "eslint \"**/*.{vue,ts,js}\"",
"lint:fix": "eslint \"**/*.{vue,ts,js}\" --fix",
"tsc-check": "vue-tsc --noEmit",
"validate-code": "concurrently \"npm run tsc-check\" \"npm run lint\""
},
"dependencies": {
"@googlemaps/js-api-loader": "^1.13.6",
"@types/angular": "^1.8.3",
"@vitejs/plugin-vue2": "^1.1.2",
"@vueuse/core": "^8.5.0",
"@vueuse/integrations": "^8.7.5",
"axios": "^0.26.1",
"gsap": "^3.10.0",
"lodash": "^4.17.21",
"mitt": "^3.0.0",
"portal-vue": "^2.1.7",
"postcss": "^8.4.12",
"postcss-loader": "^6.2.1",
"tailwindcss": "^1",
"tslib": "^2.3.1",
"universal-cookie": "^4.0.4",
"vue": "^2.7.10",
"vue-query": "^2.0.0-beta.10"
},
"devDependencies": {
"@types/google.maps": "^3.49.0",
"@vitejs/plugin-legacy": "^1.8.2",
"@vue/eslint-config-typescript": "^11.0.0",
"concurrently": "^7.1.0",
"eslint": "^8.10.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^9.4.0",
"husky": "^7.0.4",
"postcss-import": "^14.1.0",
"postcss-nested": "^5.0.6",
"typescript": "^4.5.4",
"unplugin-icons": "^0.14.3",
"unplugin-vue-components": "^0.19.6",
"vite": "^2.8.6"
}
}
Next step will be, to try using vue-query in a clean vue2.7 project, and try using public api's for testing
Vue 2.7 seems to be working just fine. Diff for 2.x-basic example - https://github.com/DamianOsipiuk/vue-query/commit/8723b99014acc2530abaf070424bf4f81d34f5b1
Vue 2.7 seems to be working just fine. Diff for 2.x-basic example - 8723b99
Okay, then i'll look further into our own setup, thanks :)
@DamianOsipiuk The main difference that i can find in the repo you linked to is that in vue 2.7 we cannot install @vur/composition-api
because it is built into 2.7, but, in your example you use createApp to create a new vue App.
I have tested on a base vue 2.7 set with new Vue()
and it does seem to work there, but still no luck on our "frankenstein" project.
Will keep trying more stuff and see if i can get something working :)
Yeah, for that reason I have provided a diff to accommodate example to v2.7 which do not use composition API. https://github.com/DamianOsipiuk/vue-query/commit/8723b99014acc2530abaf070424bf4f81d34f5b1
It's weird that it was working before, but does not work with 2.7 as there suppose to be no breaking changes.
It would be very hard to nail down what exactly is broken without the ability to set breakpoints in code.
The non standard way of instantiating Vue component might be the culprit, as Query client context propagation is done via mixin in Vue 2.
If nothing works, maybe gradual migration to Vue 3 via new integration layer would be an option and leaving already working code on v2.6?
Sadly i dont thinks its an option ti slowly migrate to vue3, since we need IE11 support. Plus we are already slowly migrating from angular1 to vue2 :)
I have now also asked the vue discord, and a link to this issue has been provided to it
Update, i have come to the conclusion that the issue doesn't lie with the installation of the plugin, since when i log the vue instance from components before useQuery is called, i can see under _provided
that VUE_QUERY_CLIENT: QueryClient2
is there. So now im even more at a loss :/
If this is still an issue, you can try with @tanstack/vue-query
There you can provide queryClient
as an option to useQuery
hook, basically skipping Vue context, which should solve your issue.
Hello 👋 After updating from vue2.6 with vue-demi, to vue2.7 without vue-demi, im running into an issue where Vue no longer is registering the VueQueryPlugin. here is how i have been using the plugin up till now:
Vue.use(VueQueryPlugin)
.Previously i was using vue-query1.26 but just updated to vue-query2, but it is still not working