-
Notifications
You must be signed in to change notification settings - Fork 6
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
On forceUpdate
and connectedElements
#2
Comments
How do you mean? It's a separate library and only shares the
As the module is independent, a component could subscribe to it using the It's probably not documented as well as it could be. There's a lot going on and it's a hard concept to describe quickly. But there's probably still room to improve. I'm not sure an event is necessary though, as if the element is connected to the DOM and entered into the |
Sure. I should have said FYI: Here's an additional implementation (which seems to work for my demos). [Edit]: Fixed a lot of issues of the first versions// === exports =======================================================
export { detectLocale, observeLocale }
// === constants / module data =======================================
const LOCALE_OBSERVATION = 'locale-observation'
const localeByElem = new Map<HTMLElement, string | null>()
// === types =========================================================
type LocaleObservationApi = {
subscribe(subscriber: () => void): () => void
notify(): void
}
type LocaleObservationEvent = {
type: typeof LOCALE_OBSERVATION
detail(api: LocaleObservationApi): void
}
declare global {
interface DocumentEventMap {
[LOCALE_OBSERVATION]: LocaleObservationEvent
}
}
// === default api ===================================================
const defaultApi = ((): LocaleObservationApi => {
let initialized = false
const subscribers = new Set<() => void>()
const notify = () => subscribers.forEach((it) => it())
return {
subscribe(subscriber) {
if (!initialized) {
new MutationObserver(notify).observe(document, {
attributes: true,
attributeFilter: ['lang'],
subtree: true
})
}
const sub = () => subscriber()
subscribers.add(sub)
initialized = true
return () => subscribers.delete(sub)
},
notify
}
})()
// === locale observation functions ==================================
const { subscribe, notify } = ((): LocaleObservationApi => {
let api: LocaleObservationApi | null = null
document.dispatchEvent(
new CustomEvent(LOCALE_OBSERVATION, {
detail: (otherApi: LocaleObservationApi) => (api = otherApi)
})
)
if (!api) {
api = defaultApi
document.addEventListener(LOCALE_OBSERVATION, (ev) => ev.detail(defaultApi))
}
return api
})()
// === getLocale =====================================================
function getLocale(elem: HTMLElement): string | null {
let el: Element = elem
while (el && !(el instanceof Window) && !(el instanceof Document)) {
const next = el.closest<HTMLElement>('[lang]')
if (next) {
return next.lang || null
}
el = (el.getRootNode() as ShadowRoot).host
}
return null
}
// === detectLocale ==================================================
function detectLocale(elem: HTMLElement) {
const locale = localeByElem.get(elem)
return locale !== undefined ? locale : getLocale(elem)
}
// === observeLocale =================================================
function observeLocale(elem: HTMLElement, callback: () => void) {
let locale: string | null = null
let cleanup1: (() => void) | null = null
let cleanup2: (() => void) | null = null
return {
connect() {
locale = getLocale(elem)
cleanup1 = subscribe(() => {
locale = getLocale(elem)
localeByElem.set(elem, locale)
callback()
})
if (elem.getRootNode() instanceof ShadowRoot) {
const observer = new MutationObserver(notify)
observer.observe(elem, {
attributes: true,
attributeFilter: ['lang']
})
cleanup2 = () => observer.disconnect()
}
},
disconnect() {
localeByElem.delete(elem)
cleanup1 && cleanup1()
cleanup2 && cleanup2()
cleanup1 = cleanup2 = null
},
getLocale: () => locale
}
} |
This is counterintuitive. You want something to work as a first-class citizen, but you don't want to subscribe to its usage. This package really does two things:
Neither of these are provided for us by the platform, hence this library. What you're proposing introduces a non-standard API and relies on a custom event that other libraries would have to listen for. I don't see any advantage to that. It's just a different approach. Before trying to solve whatever problem you're trying to solve — which, admittedly, isn't very clear to me — you might think about what you really want to have for a higher level API. I chose Whether or not a project wants to use this as a dependency isn't a priority for me. 🤷🏻♂️ |
Okay, thanks ... then I'll close this issue. |
Just for the record (no need to answer) as this was obviously not clear and I do not want to appear impolite or whatever not clarifing it:
|
@claviska I know, it's currently not important, but just FYI: PS: Code has not been tested |
[Edit - November 2021]
This proposal was not very helpful, it can/should be ignored. For a much simpler proposal please see
#2 (comment)
That whole Shoelace localization stuff looks pretty awesome.
But what really, really bugs me is that
forceUpdate
andconnectedElements
are part of the public API and especially that they are SL specific. I think this is not really necessary and other custom element libraries could use the same "lang attribute observer" strategy as SL without depending on it.BTW, at the moment, components cannot subscribe for
lang
change notifications, this should also be fixed with the proposal below.I've not tested the code but my little brain tells me, something like this could work.
The idea is that a component asks on connect whether there's already someone who's responsible for all this
lang
attribute observation andlang
change notification stuff ... if yes, fine, then the component receives theforceUpdate
function and also can subscribe forlang
changes ... if no, the component itself will take care that someone will handle that from now on.I guess, the code might not be easily understandable, yet a bit simplified (and also be full of bugs 😉), but like said, something like that may work:
@claviska What do you think?
[Edit] Maybe it would be nice if the notification callback would also pass the current language of the element in question, anyway ...
The text was updated successfully, but these errors were encountered: