taiga-ui
taiga-ui copied to clipboard
🐞 - `FieldErrorPipe` change detection problem with `touched`-state
Which @taiga-ui/* package(s) are the source of the bug?
kit
Please provide a link to a minimal reproduction of the bug
See description
Is this issue blocking you?
Non-Blocking
Description
Preconditions: Typescript-file (pay attention what happens in constructor):
const LONG_TEXT_EXAMPLE = `
In Java: everything is an object.
In Clojure: everything is a list.
In JavaScript: everything is a terrible mistake.
`;
@Component({
selector: 'tui-text-area-example-4',
templateUrl: './index.html',
changeDetection,
encapsulation,
styleUrls: ['./index.less'],
})
export class TuiTextAreaExample4 {
readonly maxLength = 97;
readonly testForm = new FormGroup({
testValue1: new FormControl(LONG_TEXT_EXAMPLE.trim(), [
Validators.required,
Validators.maxLength(this.maxLength),
]),
});
constructor() {
this.testForm.markAllAsTouched();
}
}
Problem description:
- Use deprecated
<tui-field-error />
:
<form
class="form tui-col_md-6"
[formGroup]="testForm"
>
<label
tuiLabel
label="Write a wise thought"
class="tui-row"
>
<tui-text-area
formControlName="testValue1"
tuiHintContent="it's just a joke"
[expandable]="true"
[tuiTextfieldMaxLength]="maxLength"
[tuiTextfieldLabelOutside]="true"
>
Type it
</tui-text-area>
<tui-field-error formControlName="testValue1"></tui-field-error>
</label>
</form>

- Use new pipe FieldError
<form
class="form tui-col_md-6"
[formGroup]="testForm"
>
<label
tuiLabel
label="Write a wise thought"
class="tui-row"
>
<tui-text-area
formControlName="testValue1"
tuiHintContent="it's just a joke"
[expandable]="true"
[tuiTextfieldMaxLength]="maxLength"
[tuiTextfieldLabelOutside]="true"
>
Type it
</tui-text-area>
<tui-error
formControlName="testValue1"
[error]="[] | tuiFieldError | async"
></tui-error>
</label>
</form>
You need to trigger change detection (for example, to hover over a text-area) to show error message.
Angular version
any
Taiga UI version
2.48.0
Which browsers have you used?
- [X] Chrome
- [ ] Firefox
- [ ] Safari
- [ ] Edge
Which operating systems have you used?
- [X] macOS
- [ ] Windows
- [ ] Linux
- [ ] iOS
- [ ] Android
Probably, it is impossible to fix until fixing this issue: https://github.com/angular/angular/issues/10887#issuecomment-421289798
Deprecated FieldError component uses Default
-change detection strategy (that is why it works).
Our new pipe requires observable with changes of touched
-status.
What do you think about
constructor(
@Optional()
@Self()
@Inject(NgControl)
private readonly ngControl: NgControl | null,
// ...
) {
if (this.ngControl?.control?.markAllAsTouched) {
const markAllAsTouched = this.ngControl.control.markAllAsTouched;
this.ngControl.control.markAllAsTouched = () => {
markAllAsTouched();
this.cd.markForCheck();
}
}
}
Another not perfect solution:
export class TuiFieldErrorPipe implements PipeTransform {
private readonly isTouched$ = this.refresh$.pipe(
throttleTime(200),
startWith(null),
map(() => this.touched),
distinctUntilChanged(),
tuiZonefree(this.ngZone),
);
// ...
constructor(
@Inject(NgZone) private readonly ngZone: NgZone,
@Inject(ANIMATION_FRAME) private readonly refresh$: Observable<unknown>,
) {
// ...
transform(order: readonly string[]): Observable<TuiValidationError | null> {
this.order = order;
return this.isTouched$.pipe(switchMap(() => this.computedError));
}
// ...
}
@vladimirpotekhin @waterplea let's discuss)
We have utility function markControlAsTouchedAndValidate
. Would it help? Let's not make messy workarounds.
Utility markControlAsTouchedAndValidate
does not help(
fixed by https://github.com/Tinkoff/taiga-ui/pull/3349