Skip to content

Commit

Permalink
Merge pull request #1884 from zyfra/fix/issue-v3-1190
Browse files Browse the repository at this point in the history
fix(components/input-text): incorrect behavior occurring in PrizmInputComponent when NgxMaskDirective is applied and the value changes from an empty state. #1190
  • Loading branch information
ickisIckis authored Jul 22, 2024
2 parents df22a1f + 9f6c6e6 commit 1eb4842
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 98 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectorRef, Component, ElementRef, Optional, Self } from '@angular/core';
import { ChangeDetectorRef, Component, ElementRef, Optional, Renderer2, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';
import { PrizmDestroyService } from '@prizm-ui/helpers';
import { PrizmInputControl } from '../common/base/input-control.class';
Expand Down Expand Up @@ -43,9 +43,10 @@ export class PrizmInputBlockComponent extends PrizmInputTextComponent implements
@Optional() @Self() public readonly ngControl_: NgControl,
public readonly elementRef_: ElementRef<HTMLInputElement | HTMLTextAreaElement>,
private readonly destroy_: PrizmDestroyService,
private readonly cdr_: ChangeDetectorRef
private readonly cdr_: ChangeDetectorRef,
private readonly renderer_: Renderer2
) {
super(ngControl_, elementRef_, destroy_, cdr_);
super(ngControl_, elementRef_, destroy_, cdr_, renderer_);

if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
OnInit,
Optional,
Output,
Renderer2,
Self,
} from '@angular/core';
import { NgControl, NgModel, UntypedFormControl, Validators } from '@angular/forms';
Expand Down Expand Up @@ -113,7 +114,7 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.ngControl.control?.patchValue(value);
});
} else {
this._inputValue.value = value as string;
this.updateValue(value);
this.updateEmptyState();
this.stateChanges.next();
}
Expand Down Expand Up @@ -171,7 +172,8 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
@Optional() @Self() public readonly ngControl: NgControl,
public readonly elementRef: ElementRef<HTMLInputElement | HTMLTextAreaElement>,
private readonly destroy: PrizmDestroyService,
private readonly cdr: ChangeDetectorRef
private readonly cdr: ChangeDetectorRef,
private readonly renderer2_: Renderer2
) {
super();
this.nativeElementType = elementRef.nativeElement.type;
Expand Down Expand Up @@ -205,14 +207,6 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.stateChanges.complete();
}

@HostListener('input', ['$event'])
private onInput(): void {
this.updateEmptyState();
this.stateChanges.next();
this.updateValue(this.value);
this.valueChanged.next(this.value);
}

@HostListener('focus', ['$event'])
private onFocus(): void {
this.focused = true;
Expand Down Expand Up @@ -262,28 +256,23 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
}

private updateEmptyState(): void {
this.empty = !(
(this.elementRef.nativeElement.value && this.elementRef.nativeElement.value.length) ||
(this.ngControl && this.ngControl.value) ||
(this.ngControl instanceof NgModel && this.ngControl.model)
);
this.empty = !(this.elementRef.nativeElement.value && this.elementRef.nativeElement.value.length);
}

private updateErrorState(): void {
this.invalid = Boolean(this.ngControl && this.ngControl.invalid);
}

private updateValue(value: VALUE): void {
if (value !== this.ngControl?.value) this.ngControl?.control?.setValue(value);
if (value !== this.value) this._inputValue.value = value as string;
if (value !== this.value) this.renderer2_.setProperty(this._inputValue, 'value', value);
this.inputHint?.updateHint();
}

public clear(event: MouseEvent): void {
if (this.disabled) return;

this.updateValue(null as VALUE);

this.ngControl?.control?.setValue('');
this.updateEmptyState();
this.updateErrorState();

Expand All @@ -306,13 +295,21 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
public markControl(options: { touched?: boolean; dirty?: boolean }): void {
const { touched, dirty } = options;

if (touched) {
if (typeof touched === 'boolean') {
this._touched = true;
this.ngControl?.control?.markAsTouched();
if (touched) {
this.ngControl?.control?.markAsTouched();
} else {
this.ngControl?.control?.markAsUntouched();
}
}

if (dirty) {
this.ngControl?.control?.markAsDirty();
if (typeof dirty === 'boolean') {
if (dirty) {
this.ngControl?.control?.markAsDirty();
} else {
this.ngControl?.control?.markAsPristine();
}
}

this.stateChanges.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import {
OnInit,
Optional,
Output,
Renderer2,
Self,
} from '@angular/core';
import { NgControl, NgModel, UntypedFormControl, Validators } from '@angular/forms';
import { NgControl, Validators } from '@angular/forms';
import { PrizmDestroyService } from '@prizm-ui/helpers';
import { takeUntil, tap } from 'rxjs/operators';
import { PrizmInputControl } from '../common/base/input-control.class';
Expand All @@ -23,7 +24,7 @@ import { MaskDirective } from 'ngx-mask';

@Component({
selector:
// eslint-disable-next-line @angular-eslint/component-selector
// eslint-disable-next-line @angular-eslint/component-selector
'input[prizmInput]:not([type=number]), textarea[prizmInput], input[prizmInputPassword]',
template: '',
// eslint-disable-next-line @angular-eslint/no-host-metadata-property
Expand Down Expand Up @@ -73,6 +74,11 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri

private _disabled = false;


@Input()
@HostBinding('attr.placeholder')
placeholder?: string;

/**
* @deprecated
* Required input
Expand Down Expand Up @@ -108,7 +114,7 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.ngControl.control?.patchValue(value);
});
} else {
this._inputValue.value = value as string;
this.updateValue(value);
this.updateEmptyState();
this.stateChanges.next();
}
Expand Down Expand Up @@ -166,7 +172,8 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
@Optional() @Self() public readonly ngControl: NgControl,
public readonly elementRef: ElementRef<HTMLInputElement | HTMLTextAreaElement>,
private readonly destroy: PrizmDestroyService,
private readonly cdr: ChangeDetectorRef
private readonly cdr: ChangeDetectorRef,
private readonly renderer2_: Renderer2,
) {
super();
this.nativeElementType = elementRef.nativeElement.type;
Expand All @@ -183,7 +190,7 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.parentLayout?.clear
.pipe(
tap(() => {
this.maybeMask, this.maybeMask?.writeValue(null as any);
this.maybeMask?.writeValue(null as any);
}),
takeUntil(this.destroy)
)
Expand All @@ -200,14 +207,6 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.stateChanges.complete();
}

@HostListener('input', ['$event'])
private onInput(): void {
this.updateEmptyState();
this.stateChanges.next();
this.updateValue(this.value);
this.valueChanged.next(this.value);
}

@HostListener('focus', ['$event'])
private onFocus(): void {
this.focused = true;
Expand Down Expand Up @@ -257,28 +256,23 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
}

private updateEmptyState(): void {
this.empty = !(
(this.elementRef.nativeElement.value && this.elementRef.nativeElement.value.length) ||
(this.ngControl && this.ngControl.value) ||
(this.ngControl instanceof NgModel && this.ngControl.model)
);
this.empty = !(this.elementRef.nativeElement.value && this.elementRef.nativeElement.value.length);
}

private updateErrorState(): void {
this.invalid = Boolean(this.ngControl && this.ngControl.invalid);
}

private updateValue(value: VALUE): void {
if (value !== this.ngControl?.value) this.ngControl?.control?.setValue(value);
if (value !== this.value) this._inputValue.value = value as string;
if (value !== this.value) this.renderer2_.setProperty(this._inputValue, 'value', value);
this.inputHint?.updateHint();
}

public clear(event: MouseEvent): void {
if (this.disabled) return;

this.updateValue(null as VALUE);

this.ngControl?.control?.setValue('');
this.updateEmptyState();
this.updateErrorState();

Expand All @@ -301,13 +295,21 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
public markControl(options: { touched?: boolean; dirty?: boolean }): void {
const { touched, dirty } = options;

if (touched) {
if (typeof touched === 'boolean') {
this._touched = true;
this.ngControl?.control?.markAsTouched();
if (touched) {
this.ngControl?.control?.markAsTouched();
} else {
this.ngControl?.control?.markAsUntouched();
}
}

if (dirty) {
this.ngControl?.control?.markAsDirty();
if (typeof dirty === 'boolean') {
if (dirty) {
this.ngControl?.control?.markAsDirty();
} else {
this.ngControl?.control?.markAsPristine();
}
}

this.stateChanges.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import {
OnInit,
Optional,
Output,
Renderer2,
Self,
} from '@angular/core';
import { NgControl, NgModel, UntypedFormControl, Validators } from '@angular/forms';
import { NgControl, Validators } from '@angular/forms';
import { PrizmDestroyService } from '@prizm-ui/helpers';
import { takeUntil, tap } from 'rxjs/operators';
import { PrizmInputControl } from '../common/base/input-control.class';
Expand All @@ -23,7 +24,7 @@ import { NgxMaskDirective } from 'ngx-mask';

@Component({
selector:
// eslint-disable-next-line @angular-eslint/component-selector
// eslint-disable-next-line @angular-eslint/component-selector
'input[prizmInput]:not([type=number]), textarea[prizmInput], input[prizmInputPassword]',
template: '',
// eslint-disable-next-line @angular-eslint/no-host-metadata-property
Expand Down Expand Up @@ -73,6 +74,10 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri

private _disabled = false;

@Input()
@HostBinding('attr.placeholder')
placeholder?: string;

/**
* @deprecated
* Required input
Expand Down Expand Up @@ -108,7 +113,7 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.ngControl.control?.patchValue(value);
});
} else {
this._inputValue.value = value as string;
this.updateValue(value);
this.updateEmptyState();
this.stateChanges.next();
}
Expand All @@ -132,7 +137,8 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri

readonly maybeMask = inject(NgxMaskDirective, {
optional: true,
});
}) as NgxMaskDirective;

readonly parentLayout = inject(PrizmInputLayoutComponent, {
optional: true,
});
Expand Down Expand Up @@ -165,7 +171,8 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
@Optional() @Self() public readonly ngControl: NgControl,
public readonly elementRef: ElementRef<HTMLInputElement | HTMLTextAreaElement>,
private readonly destroy: PrizmDestroyService,
private readonly cdr: ChangeDetectorRef
private readonly cdr: ChangeDetectorRef,
private readonly renderer2_: Renderer2,
) {
super();
this.nativeElementType = elementRef.nativeElement.type;
Expand All @@ -182,7 +189,7 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.parentLayout?.clear
.pipe(
tap(() => {
this.maybeMask, this.maybeMask?.writeValue(null as any);
this.maybeMask?.writeValue(null as any);
}),
takeUntil(this.destroy)
)
Expand All @@ -199,14 +206,6 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
this.stateChanges.complete();
}

@HostListener('input', ['$event'])
private onInput(): void {
this.updateEmptyState();
this.stateChanges.next();
this.updateValue(this.value);
this.valueChanged.next(this.value);
}

@HostListener('focus', ['$event'])
private onFocus(): void {
this.focused = true;
Expand Down Expand Up @@ -256,28 +255,23 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
}

private updateEmptyState(): void {
this.empty = !(
(this.elementRef.nativeElement.value && this.elementRef.nativeElement.value.length) ||
(this.ngControl && this.ngControl.value) ||
(this.ngControl instanceof NgModel && this.ngControl.model)
);
this.empty = !(this.elementRef.nativeElement.value && this.elementRef.nativeElement.value.length);
}

private updateErrorState(): void {
this.invalid = Boolean(this.ngControl && this.ngControl.invalid);
}

private updateValue(value: VALUE): void {
if (value !== this.ngControl?.value) this.ngControl?.control?.setValue(value);
if (value !== this.value) this._inputValue.value = value as string;
if (value !== this.value) this.renderer2_.setProperty(this._inputValue, 'value', value);
this.inputHint?.updateHint();
}

public clear(event: MouseEvent): void {
if (this.disabled) return;

this.updateValue(null as VALUE);

this.ngControl?.control?.setValue('');
this.updateEmptyState();
this.updateErrorState();

Expand All @@ -300,13 +294,21 @@ export class PrizmInputTextComponent<VALUE extends string | number | null = stri
public markControl(options: { touched?: boolean; dirty?: boolean }): void {
const { touched, dirty } = options;

if (touched) {
if (typeof touched === 'boolean') {
this._touched = true;
this.ngControl?.control?.markAsTouched();
if (touched) {
this.ngControl?.control?.markAsTouched();
} else {
this.ngControl?.control?.markAsUntouched();
}
}

if (dirty) {
this.ngControl?.control?.markAsDirty();
if (typeof dirty === 'boolean') {
if (dirty) {
this.ngControl?.control?.markAsDirty();
} else {
this.ngControl?.control?.markAsPristine();
}
}

this.stateChanges.next();
Expand Down
Loading

0 comments on commit 1eb4842

Please sign in to comment.