scania-digital-design-system / tegel

Tegel Design System
https://tegel.scania.com
MIT License
19 stars 14 forks source link

[Bug report]: TdsHeaderItem ignores slot="end" when *ngIf directive value changes #528

Open Patrick2607 opened 8 months ago

Patrick2607 commented 8 months ago

Requirements before reporting

Package versions

@scania/tegel-angular: 1.6.1

Browser

Firefox

Framework

Angular

Version

Angular 16.2.0

Reproduction steps

  1. Write a TdsHeader and one or more TdsHeaderItem elements in your html template
  2. Set an *ngIf directive on the TdsHeaderItem together with slot="end"
  3. Change the value *ngIf directive

Code example

HTML template:

<tds-header *ngIf="vm$ | async as vm">
  <!-- Other items -->
  <tds-header-item slot="end" *ngIf="vm.user" title="Orders">
    <a routerLink="/orders">Orders</a>
  </tds-header-item>
  <!-- Other items -->
</tds-header>

TS component:

export class NavbarComponent {  
  private readonly document: Document = inject(DOCUMENT);

  // KeyPress event to toggle the ngIf directive
  private readonly user$ = fromEvent<KeyboardEvent>(
    this.document,
    'keydown'
  ).pipe(
    filter((e: KeyboardEvent) => e.key === 'x'),
    startWith(undefined),
    scan((acc: boolean) => !acc, false)
  );

  // View model for the html template
  readonly vm$ = combineLatest({
    user: this.user$,
    // Other exposed variables
  }).pipe(
    //concatMap((value) => of(null, value).pipe(delay(0)))
  );
}

Please note that I’ve constructed a basic example to illustrate this issue. You can replicate the behavior by copying and pasting the provided code into your environment. Once you’ve done that, press X in your browser to toggle the value of the *ngIf directive. Initially, you’ll observe that it renders on the right side. However, upon disabling and re-enabling it, the rendering shifts to the left instead of maintaining its position on the right.

I’ve implemented a temporary workaround for this issue by triggering a ‘re-render’ of the entire TdsHeader component whenever the view model vm$ emits. However, this is merely a quick fix as it causes all child components to re-render as well. To illustrate this, please uncomment the concatMap function operator in the pipe. Here’s what happens: when vm$ emits, it first emits a null value. This effectively unrenders the entire TdsHeader component due to its *ngIf directive: <tds-header *ngIf="vm$ | async as vm">. Following this, it emits the actual value, which triggers a re-render of the entire TdsHeader component. As a result, the TdsHeaderItems are correctly positioned.

Screenshots

tdsheader_bugreport

Expected behaviour

The TdsHeaderItem element should consistently stay anchored to the right side, regardless of whether the element has been re-rendered or not.

Console errors

No response

Contact information

patrick.groot.koerkamp@scania.com

luistabotelho commented 2 days ago

This issue is still valid in 1.19.

Example use case is having a little help button in a TdsHeadItem with slot="end", but you only want to show this help if a user is authenticated. If the user loads the website and then authenticates the TdsHeaderItem appears to the right, ignoring slot="end". Reloading the page while authenticated fixes it as then the header is created with the help button already visible.

ckrook commented 2 days ago

Hello @luistabotelho & @Patrick2607 , We have looked into this issue and concluded that we cannot solve this at the moment because the proposed solution would introduce a breaking change. We will look at this in the future when we are planning for a release of Tegel with breaking changes. Plan and timing for this is to be defined.