-
-
Notifications
You must be signed in to change notification settings - Fork 342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom Elements: Handle child component #646
Comments
The same error occurs when using async custom element with : customElements.define(
'my-element',
defineCustomElement(defineAsyncComponent(() => import('MyComponent.vue')))
) (but it makes sense because |
Thank you for feedback! Unfortunately, this is a limitation of Vue Provide / Inject. 😞 Vue docs says:
https://v3.vuejs.org/guide/web-components.html#definecustomelement This means that if you use a Vue component from a custom element that is a web component, the inject will not work. |
Thanks for your answer ! I missed that important info ! I created an issue in the vue-next repo : vuejs/core#4476 And will use a custom implementation of import { getCurrentInstance, InjectionKey } from 'vue'
import { I18nInjectionKey } from 'vue-i18n'
export function deepInject<T> (key: InjectionKey<T> | string): T | undefined {
let inst = getCurrentInstance()
if (inst === null) {
throw new Error('getCurrentInstance returned null')
}
inst = inst.parent
if (inst === null) {
return
}
while (inst !== null) {
// @ts-expect-error
if (key in inst.provides) {
// @ts-expect-error
return inst.provides[key]
}
inst = inst.parent
}
}
interface Options {
messages?: Record<string, Record<string, string>>
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function useI18n (options?: Options) {
const instance = deepInject(I18nInjectionKey)
if (instance === undefined) {
throw new Error('i18n not found in context')
}
const { global } = instance
// merge locale messages
const messages = options?.messages ?? {}
const locales = Object.keys(messages)
if (locales.length > 0) {
locales.forEach(locale => {
global.mergeLocaleMessage(locale, messages[locale])
})
}
return global
} It does not cover all use-cases of the original implementation but it covers my use-case. Thanks! |
I think the provide/inject limitation does not effect this. I tried providing the i18n instance from a vue web component and than inject this in a child vue component and it worked fine. PluginProvider.ce.vue
CustomElement.ce.vue
ChildElement.vue
|
We also run into this issue Please checkout this implementation which just create a wrapper component which doesn't need to be mounted on the application but can be mounted on any vue component which will be converted to web component It would be nice to have this feature inside native i18n So it can be used to create web components without App context |
That's interesting! |
Reporting a bug?
When calling
useI18n
from a component which is a children from a Custom Element, it throws :here : https://github.com/intlify/vue-i18n-next/blob/24b6d60a711ba591b1abdae937930c1615c98d81/packages/vue-i18n-core/src/i18n.ts#L604
This is because the child components do not have
instance.isCE
.Would it be possible to :
inject
even if!isCE
and check for its result ?Expected behavior
Should not throw
Reproduction
NA
System Info
Screenshot
No response
Additional context
No response
Validations
The text was updated successfully, but these errors were encountered: