Repository: goauthentik/authentik
File: web/src/flow/FlowExecutor.ts (TypeScript)

Code before:

        this.refresh().then(() => {
            window.dispatchEvent(new AKFlowAdvanceEvent());
        });
    }

    // DOM post-processing has to happen after the render.
    public updated(changedProperties: PropertyValues<this>) {
        super.updated(changedProperties);

        document.title = match(this.challenge?.flowInfo?.title)
            .with(P.nullish, () => this.brandingTitle)
            .otherwise((title) => `${title} - ${this.brandingTitle}`);

        if (changedProperties.has("challenge") && this.challenge?.flowInfo) {
            this.layout = this.challenge?.flowInfo?.layout || FlowExecutor.DefaultLayout;
        }

        if (changedProperties.has("flowInfo") || changedProperties.has("activeTheme")) {
            this.#synchronizeFlowInfo();
        }

        const previous = Array.from(this.children).find((el) =>
            el.matches('[slot="slotted-dialog"]'),
        );
        (previous as Element | undefined)?.remove();

        if (this.challenge) {
            this.renderChallenge(this.challenge);
        }
    }

    //#endregion

    //#region Public Methods

    public submit = async (
        payload?: FlowChallengeResponseRequest,
        options?: SubmitOptions,
    ): Promise<boolean> => {
        if (!payload) throw new Error("No payload provided");
        if (!this.challenge) throw new Error("No challenge provided");

        if (!this.flowSlug) {
            if (import.meta.env.AK_BUNDLER === "storybook") {
                this.#logger.debug("Skipping submit flow slug check in storybook");

                return true;
            }

            throw new Error("No flow slug provided");

Review comment (suggestion):
```suggestion
        const previous = Iterator.from(this.children).find((el) =>
            el.matches('[slot="slotted-dialog"]'),
        );

        previous?.remove();
```

Alternatively, direct references to the slots?

```ts
 class FlowExecutor {
    protected dialogSlot: HTMLSlotElement;
    protected placeholderSlot: HTMLSlotElement;

    constructor() {
        configureSentry();

        super();

        this.dialogSlot = this.ownerDocument.createElement("slot");
        this.dialogSlot.name = "slotted-dialog";

        this.placeholderSlot = this.ownerDocument.createElement("slot");
        this.placeholderSlot.name = "placeholder";
        this.placeholderSlot.classList.add("slotted-content");
    }
```


Code after:
                const parsedError = await parseAPIResponseError(error);
                showAPIErrorMessage(parsedError);
                this.setFlowErrorChallenge(parsedError);
                return false;
            })
            .finally(() => {
                this.loading = false;
            });
    };

    public async firstUpdated(changed: PropertyValues<this>): Promise<void> {
        super.firstUpdated(changed);

        this.refresh().then(() => {
            window.dispatchEvent(new AKFlowAdvanceEvent());
        });
    }

    // DOM post-processing has to happen after the render.
    public updated(changedProperties: PropertyValues<this>) {
        super.updated(changedProperties);

        document.title = match(this.challenge?.flowInfo?.title)
            .with(P.nullish, () => this.brandingTitle)
            .otherwise((title) => `${title} - ${this.brandingTitle}`);

        if (changedProperties.has("challenge") && this.challenge?.flowInfo) {
            this.layout = this.challenge?.flowInfo?.layout || FlowExecutor.DefaultLayout;
        }

        if (changedProperties.has("flowInfo") || changedProperties.has("activeTheme")) {
            this.#synchronizeFlowInfo();
        }
    }

    //#endregion

    //#region Public Methods

    public submit = async (
        payload?: FlowChallengeResponseRequest,
        options?: SubmitOptions,
    ): Promise<boolean> => {
        if (!payload) throw new Error("No payload provided");
        if (!this.challenge) throw new Error("No challenge provided");

        if (!this.flowSlug) {
            if (import.meta.env.AK_BUNDLER === "storybook") {
                this.#logger.debug("Skipping submit flow slug check in storybook");

                return true;