Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

[feat]: slotController synchronous `hostUpdated()`

Đang mở
#3,103 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
55/100
Loại issue
Tính năng
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
typescript
Lĩnh vực
frontend

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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, no requestUpdate(), 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: hostConnected clears records → next render → hostUpdated() repopulates.

What this fixes that the current PR doesn't

  • hasSlotted() and isEmpty() have the same timing gap, they also read from #slotRecords and return incorrect results before async init completes. The hostUpdated() approach fixes all three methods.
  • Eliminates the async architecture 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

Ngôn ngữ chính
TypeScript
Star
394
Fork
107
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của patternfly/patternfly-elements

Tất cả issue của patternfly/patternfly-elements

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.