siemens / ix

Siemens Industrial Experience is a design system for designers and developers, to consistently create the perfect digital experience for industrial software products.
https://ix.siemens.io/
MIT License
205 stars 69 forks source link

[IxSelect] Form validation styles are broken #1290

Open tiagogviegas opened 5 months ago

tiagogviegas commented 5 months ago

Prerequisites

What happened?

IxSelect component form validation styling is broken. Error message styling is different from input element.

image

What type of frontend framework are you seeing the problem on?

JavaScript

Which version of iX do you use?

v2.2.1

Code to produce this issue.

<form class="was-validated" style="width: 400px">
    <div style="margin-bottom: 24px">
      <input type="text" class="is-invalid" />
      <div class="invalid-feedback">Error Message</div>
    </div>

    <div>
      <ix-select class="is-invalid" style="width: 100%">
        <ix-select-item class="" label="Option 1" value="1"></ix-select-item>
        <ix-select-item class="" label="Option 2" value="2"></ix-select-item>
      </ix-select>
      <div class="invalid-feedback">Error Message</div>
    </div>
</form>
github-actions[bot] commented 5 months ago

🤖 Hello @tiagogviegas

Your issue will be analyzed and is part of our internal workflow. To get informed about our workflow please checkout the Contributing Guidelines

JIRA: IX-903

woidbua commented 2 months ago

Unfortunately, the ix-select also does not work correctly as a FormControl in an Angular environment. Errors are not properly displayed, and styles are not applied because the input element itself is enclosed in a shadow root. Therefore, we wrapped the ix-select in Angular and used a Mutation Observer to modify the shadow root, allowing us to apply styles directly to the input element.

It’s not an elegant solution, but it works. It would be great if ix-select could support validation natively in the future and style the input element accordingly.

@ViewChild('ixSelect', { static: false, read: ElementRef }) ixSelect!: ElementRef;

...

ngAfterViewInit() {
  const shadowRoot = this.ixSelect.nativeElement.shadowRoot;
  if (!shadowRoot) return;

  this.observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.attributeName === 'class') {
        const selectDivElement = shadowRoot.querySelector('.select');
        if (this.isFormControlInvalid()) {
          FormValidationStylesUtil.setInvalidInputBackgroundStyles(this.renderer, selectDivElement);
        } else {
          FormValidationStylesUtil.removeInvalidInputBackgroundStyles(this.renderer, selectDivElement);
        }
      }
    });
  });

  ...

export function setInvalidInputBackgroundStyles(renderer: Renderer2, element: HTMLElement) {
  if (!element) return;
  renderer.setStyle(element, 'background-color', 'var(--theme-input-error--background)');
  renderer.setStyle(element, 'border-color', 'var(--theme-input-error--border-color)');
}

export function removeInvalidInputBackgroundStyles(renderer: Renderer2, element: HTMLElement) {
  if (!element) return;
  renderer.removeStyle(element, 'background-color');
  renderer.removeStyle(element, 'border-color');
}
matthiashader commented 3 weeks ago

Will be closed by #1318.