Theme issue when having an OnPush component inside igx-tabs or igx-stepper
Description
Theme is always Material having an OnPush component inside igx-tabs or igx-stepper.
- igniteui-angular version: 17.1.0
- browser: all
Steps to reproduce
- Set Theme to Fluent
- Create an OnPush form with igx-inputs inside
- In the main view add a tabs component with a Form instance in each tab
- Run
Result
The Form inputs get rendered as Material theme. After clicking one of them they change to fluent.
Note: If I add [selected]="true" to the first tab, then it fixes for it but it still happens on the 2nd tab.
Expected result
The inputs should render as Fluent from the beginning.
Attachments
https://stackblitz.com/edit/vn4fjr?file=src%2Fapp%2Ftabs-sample-3%2Ftabs-sample-3.component.html
Honestly, the only viable solution I can think of right now (after numerous ugly attempts to magically update the theme from within the input group) is to just manually call detectChanges() in ngAfterViewChecked. Since the theme is read from the --theme CSS variable, it's difficult to read the CSS prop from within the input group component when it's inside another component with OnPush strategy set without resorting to ugly stuff that try to circumvent the angular railguards.
export class MyFormComponent implements AfterViewChecked {
constructor(private cdr: ChangeDetectorRef) {}
public ngAfterViewChecked() {
this.cdr.detectChanges();
}
}
The other approach (if you are concerned about performance) is to set the theme property directly on each igx-input-group.
<igx-input-group type="line" theme="fluent">
<input igxInput name="fullName1" type="text" />
<label igxLabel for="fullName1">Full Name</label>
<igx-suffix>
<igx-icon>person</igx-icon>
</igx-suffix>
</igx-input-group>
@simeonoff
public ngAfterViewChecked() {
this.cdr.detectChanges();
}
I believe this will perpetually check for changes and not just for this component but for everything up in the tree.
This is how I believe it should be done, on inputgroup component which is the one that's making the assumption that has access to the css props.
export class InputGroupComponent implements DoCheck, {
#lastIsConnected: boolean | undefined;
constructor(
private elementRef: ElementRef<unknown>,
private cdr: ChangeDetectorRef,
) { }
ngDoCheck() {
const isConnected = this.elementRef.nativeElement?.isConnected;
if (this.#lastIsConnected === false && isConnected) {
// Trigger change detection when changing from disconnected to connected state
// To force the component to re-render once they get attached in OnPush context.
// https://github.com/IgniteUI/igniteui-angular/issues/13958
this.cdr.markForCheck();
}
this.#lastIsConnected = isConnected;
}
}
Thanks, will try this to see if it resolves to problem.
It seems that despite the documentation ngDoCheck is not called inside an OnPush context that is not being checked.
I tried a different approach instead, it's a workaround in user land:
Created a directive:
import {
Directive,
ChangeDetectorRef,
DoCheck,
ElementRef,
} from '@angular/core';
@Directive({
selector: '[checkOnConnect]',
})
export class CheckOnConnectDirective implements DoCheck {
private lastIsConnected: boolean | undefined;
constructor(
private elementRef: ElementRef<HTMLElement>,
private cdr: ChangeDetectorRef
) {}
ngDoCheck() {
const isConnected = this.elementRef.nativeElement?.isConnected;
if (this.lastIsConnected === false && isConnected) {
// Trigger change detection when changing from disconnected to connected state
// To force the component to re-render once they get attached in OnPush context.
// https://github.com/IgniteUI/igniteui-angular/issues/13958
this.cdr.markForCheck();
}
this.lastIsConnected = isConnected;
}
}
And then used it in the tab content attaching it to the OnPush component like this:
<igx-tab-content>
Form 2
<app-my-form checkOnConnect></app-my-form>
</igx-tab-content>
Full example here: https://stackblitz.com/edit/vn4fjr-ndwbqf?file=src%2Fapp%2Ftabs-sample-3%2Ftabs-sample-3.component.html
There has been no recent activity and this issue has been marked inactive.
This should be resolved by https://github.com/IgniteUI/igniteui-angular/pull/14035/files#diff-3a8eee910c2ea04cd03aa2cb41b21e94c0844017e6743d7721cabea136010cdb