[feat]: slotController synchronous `hostUpdated()`
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Facilidade para iniciantes
- 55/100
- Tipo de issue
- Funcionalidade
- Clareza
- Razoavelmente clara
- Status de atividade
- Pouca atividade
- Stack de tecnologia
- typescript
- Domínio
- frontend
Direção de pesquisa
Start by locating the slotController implementation and the SlotControllerPublicAPI declaration, then trace hostConnected, #initSlotMap, the MutationObserver, and the hasSlotted(), isEmpty(), and getSlotted() methods. Implement the synchronous lifecycle described in the issue and verify initial connection, reconnection, and child mutations produce correct slot state without an async timing gap.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Alternative approach:
synchronous hostUpdated() instead of async fallback
The current fix adds a fallback in getSlotted() to query slot elements directly when #slotRecords hasn't been populated yet. This addresses the symptom but leaves the root cause: hostConnected and #initSlotMap are async, creating a timing gap where no data source exists.
The gap also affects hasSlotted() and isEmpty(), which aren't addressed here.
Why hostConnected is async
Both hostConnected and #initSlotMap await host.updateComplete just to ensure the shadow DOM exists so they can query for elements. But Lit already provides a synchronous hook that guarantees this: hostUpdated(), which runs after every render when the DOM has been committed.
Suggested change
Make hostConnected synchronous (just sets up the MutationObserver), move record initialization to hostUpdated(), and have the MutationObserver trigger a re-render instead of calling #initSlotMap directly:
hostConnected(): void {
this.#mo.observe(this.host, { childList: true });
this.#slotRecords.clear();
}
hostUpdated(): void {
if (this.#slotRecords.size === 0) {
for (let slotName of this.#slotNames.concat(Object.values(this.#deprecations))) {
slotName ||= SlotController.default;
const slot = this.#getSlotElement(slotName);
if (slot) {
this.#slotRecords.set(slotName, new SlotRecord(slot, slotName, this.host));
}
}
if (this.#slotRecords.size > 0) {
this.host.requestUpdate();
}
}
}
The MutationObserver callback becomes:
#mo = new MutationObserver(() => this.host.requestUpdate());
And #initSlotMap can be removed entirely.
This also requires updating the SlotControllerPublicAPI declaration to match:
hostConnected?(): void;
Why this works
- First render: Records empty,
isEmpty()returns true (matches SSR server behavior).hostUpdated()populates records and calls requestUpdate(). - Second render: Records exist,
isEmpty()/getSlotted()read live DOM via SlotRecord getters, correct results.hostUpdated()sees records exist, norequestUpdate(), no infinite loop. - MutationObserver: Child changes trigger
requestUpdate()→ re-render → SlotRecord getters reflect new DOM state. No record rebuild needed since they query live DOM. - Reconnection:
hostConnectedclears records → next render →hostUpdated()repopulates.
What this fixes that the current PR doesn't
hasSlotted()andisEmpty()have the same timing gap, they also read from #slotRecords and return incorrect results before async init completes. ThehostUpdated()approach fixes all three methods.- Eliminates the
asyncarchitecture that caused the issue rather than working around it.
Trade-off
The two-render pattern on initial connection is inherent <slot> elements are created by render(), so the first render can't know about them. This was already the case with the async approach.
We can spin this off to another issue if we feel the need
Originally posted by @zeroedin in https://github.com/patternfly/patternfly-elements/issues/3093#issuecomment-4252752632
- Linguagem predominante
- TypeScript
- Estrelas
- 395
- Forks
- 107
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de patternfly/patternfly-elements
-
[bug] ssr-shims.js uses deprecated globalThis.litSsrCallConnectedCallbackTalvez já em andamento @zeroedin assumiu há 66 dias. Abertabug
patternfly/patternfly-elements#3158 · 1 responsável ·
-
chore: evaluate removing isolatedDeclarations from tsconfigTalvez livre de novo @bennypowers assumiu há 156 dias e não há nenhum pull request aberto. Aberta
patternfly/patternfly-elements#3136 · 1 comentário · 1 responsável ·
-
chore: update docs scaffolding for v6 elementsTalvez livre de novo @zeroedin assumiu há 156 dias e não há nenhum pull request aberto. Abertadocs
patternfly/patternfly-elements#3131 · 1 responsável ·
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 55/100
patternfly/patternfly-elements#3122 ·
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 38/100
patternfly/patternfly-elements#3118 ·
Todas as issues de patternfly/patternfly-elements
Issues semelhantes
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 75/100
Mantenedores costumam responder em até 1 dia
-
[Bug]: [A11y] Missing accessible name on icon-only standalone links (WCAG 2.1 SC 2.4.4, 4.1.2)Abertabug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
jaegertracing/jaeger-ui#4596 ·
Mantenedores costumam responder em até 1 dia
-
area:tui enhancement platform:macos
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 66/100
anthropics/claude-code#101490 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 66/100
netlify/netlify-mcp#75 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
Mantenedores costumam responder em até 1 dia