Skip to content
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

Clicking on month/year next/previous buttons in DatePicker causes parent form to submit #7012

Closed
slavafomin opened this issue Oct 18, 2021 · 1 comment · Fixed by #7013
Closed

Comments

@slavafomin
Copy link
Contributor

Reproduction link

https://stackblitz.com/edit/ng-zorro-antd-ivy-zmsagn

Steps to reproduce

Put DatePicker inside of a <form> and click on one of the month/year next/previous buttons.

What is expected?

DatePicker shouldn't trigger form submission.

What is actually happening?

Form submission is triggered.

Environment Info
ng-zorro-antd 12.0.1
Browser Any

This is happening, because buttons miss type="button" attribute.

@slavafomin
Copy link
Contributor Author

I have to use the following workaround to fix this issue in our application:

  /**
   * Makes sure that each button has a proper `type=button`
   * attribute, otherwise they could submit a parent form.
   */
  private fixCalendarButtons() {

    if (!('querySelector' in document)) {
      console.warn(`DOM query selector is not available`);
      return;
    }

    const element = this.getCalendarElement();

    element?.querySelectorAll('button:not([type])').forEach(
      element => element.setAttribute('type', 'button')
    );

  }

  private clearCalendarMutationObserver() {
    if (this.calendarMutationObserver) {
      this.calendarMutationObserver.disconnect();
      this.calendarMutationObserver = undefined;
    }
  }

  /**
   * Monitors calendar DOM for changes and
   * applies buttons fix automatically.
   */
  private setupCalendarMutationObserver() {

    // Clearing previous observer
    this.clearCalendarMutationObserver();

    const element = this.getCalendarElement();
    if (!element) {
      return;
    }

    this.calendarMutationObserver = (
      new MutationObserver(() => this.fixCalendarButtons())
    );

    this.calendarMutationObserver.observe(element, {
      subtree: true,
      childList: true,
    });

  }

  private getCalendarElement(): (HTMLElement | undefined) {

    if (!this.calendarElement?.nativeElement) {
      console.warn(
        `Can't obtain DatePicker DOM element, ` +
        `is it rendered?`
      );
      return;
    }

    return this.calendarElement.nativeElement;

  }

Mutation observer is needed, because some buttons are getting rendered dynamically and do change when navigating around the calendar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant