Home > Back-end >  Angular 13 reusable text input
Angular 13 reusable text input

Time:10-02

I am setting up a reusable text input that could be used with reactive forms.

I am getting the following error when i add it to the declaration array of the app module and issue ng serve.

/ Generating browser application bundles (phase: building)...C:\SPA\node_modules\typescript\lib\typescript.js:19487
        return text.replace(/{(\d )}/g, function (_match, index) { return ""   ts.Debug.checkDefined(args[ index   baseIndex]); });
                                                                                        ^

Error: Debug Failure.
    at C:\SPA\node_modules\typescript\lib\typescript.js:19487:89
    at String.replace (<anonymous>)
    at formatStringFromArgs (C:\SPA\node_modules\typescript\lib\typescript.js:19487:21)
    at Object.createDetachedDiagnostic (C:\SPA\node_modules\typescript\lib\typescript.js:19503:20)
    at parseErrorAtPosition (C:\SPA\node_modules\typescript\lib\typescript.js:30898:42)
    at parseErrorAt (C:\SPA\node_modules\typescript\lib\typescript.js:30905:13)
    at parseErrorAtCurrentToken (C:\SPA\node_modules\typescript\lib\typescript.js:30892:13)
    at parseErrorForInvalidName (C:\SPA\node_modules\typescript\lib\typescript.js:31130:17)
    at parseErrorForMissingSemicolonAfter (C:\SPA\node_modules\typescript\lib\typescript.js:31102:21)
    at parseExpressionOrLabeledStatement (C:\SPA\node_modules\typescript\lib\typescript.js:34992:21) 

My Environment

Angular CLI: 13.0.2
Node: 16.13.0
Package Manager: npm 8.1.3
OS: win32 x64

Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.1300.2 (cli-only)
@angular-devkit/core         13.0.2 (cli-only)
@angular-devkit/schematics   13.0.2 (cli-only)
@schematics/angular          13.0.2 (cli-only)

Here is the code

text-input.component.ts

import { Component, Input, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';

@Component({
  selector: 'app-text-input',
  templateUrl: './text-input.component.html',
  styleUrls: ['./text-input.component.css']
})
export class TextInputComponent implements ControlValueAccessor {
  
  @Input() label: string = '';
  @Input() labelMustMatch: string = '';
  @Input() placeHolder: string = '';
  @Input() type: string = 'text';

  constructor(@Self() public ngControl: NgControl) { 
    this.ngControl.valueAccessor = this;
  }

  writeValue(obj: any): void {
    
  }

  registerOnChange(fn: any): void {
    
  }

  registerOnTouched(fn: any): void {
  
  }

  setDisabledState?(isDisabled: boolean): void {}
}

text-input.component.html

<input 
    [class.is-invalid]="ngControl.invalid && ngControl.touched && ngControl.dirty"
    type={{ type }} 
     
    [formControl]="$any(ngControl.control)"  
    placeholder={{ placeHolder }}
>
<!--required-->
<div  *ngIf="ngControl.control.errors?.required">
    {{label}} is required
</div>
<!--minlength-->
<div  *ngIf="ngControl.control.errors?.minlength">
    {{label}} must be minimum {{ngControl.control.errors.minlength['requiredLength']}} characters
</div>
<!--maxlength-->
<div  *ngIf="ngControl.control.errors?.maxlength">
    {{label}} must be maximum {{ngControl.control.errors.maxlength['requiredLength']}} characters
</div>
<!--onlyChar-->
<div  *ngIf="ngControl.control.errors.onlyChar">
    {{label}} must be only characters
</div>
<!--onlyCharWithSpace-->
<div  *ngIf="ngControl.control.errors.onlyCharWithSpace">
    {{label}} must be only characters and space
</div>
<!--mustMatch-->
<div  *ngIf="ngControl.control.errors.mustMatch">
    {{labelMustMatch}} do not match
</div>
<!--passwordStrength-->
<div  *ngIf="ngControl.control.errors.passwordStrength">
    {{label}} must have an upper case, lower case and a number
</div>

and then using it inside the parent

<app-text-input [formControl]="registerForm.controls['userName']" [label]="'User name'" [placeHolder]="'user name'"></app-text-input>

How can i fix the error?

CodePudding user response:

I think you may have a typo in these lines:

type={{ type }}
placeholder={{ placeHolder }}

The interpolated values should be wrapped in " quotes:

type="{{ type }}"
placeholder="{{ placeHolder }}"

You may also need to add optional chaining ? to control errors, like following:

*ngIf="ngControl.control.errors?.mustMatch"

Full example:

    <input 
      [class.is-invalid]="ngControl.invalid && ngControl.touched && ngControl.dirty"
      type="{{ type }}"
       
      [formControl]="$any(ngControl.control)"  
      placeholder="{{ placeHolder }}"
    >
    <!--required-->
    <div  *ngIf="ngControl.control.errors?.required">
      {{label}} is required
    </div>
    <!--minlength-->
    <div  *ngIf="ngControl.control.errors?.minlength">
      {{label}} must be minimum {{ngControl.control.errors.minlength['requiredLength']}} characters
    </div>
    <!--maxlength-->
    <div  *ngIf="ngControl.control.errors?.maxlength">
      {{label}} must be maximum {{ngControl.control.errors.maxlength['requiredLength']}} characters
    </div>
    <!--onlyChar-->
    <div  *ngIf="ngControl.control.errors?.onlyChar">
      {{label}} must be only characters
    </div>
    <!--onlyCharWithSpace-->
    <div  *ngIf="ngControl.control.errors?.onlyCharWithSpace">
      {{label}} must be only characters and space
    </div>
    <!--mustMatch-->
    <div  *ngIf="ngControl.control.errors?.mustMatch">
      {{labelMustMatch}} do not match
    </div>
    <!--passwordStrength-->
    <div  *ngIf="ngControl.control.errors?.passwordStrength">
      {{label}} must have an upper case, lower case and a number
    </div>
  • Related