matInput binded to context property conflicts with i18n extraction but not on regular serve

140 views Asked by At

I have that piece of code of a reactive form that compiles right and is well executed with the matInput directive which is binded, but when I run the angular cli command for internationalisation (ng xi18n), then I got the following error ERROR in Can't bind to 'matInput' since it isn't a known property of 'input'. I don't understand that error on i18n extract but not on regular execution. When I remove the bind on the matInput it works well on both exec and i18n extract.

Here is why I use matInput binded (so as [matInput]): in my ts file, I defined a context per form-field that tells if it needs a directive or not (matInput and required) and that gives the value of the directives that need one (formControlName, type and placeHolder):

public myForm: FormGroup
public emailContext: any
public nameContext: any
public passwordContext: any

constructor(private fb: FormBuilder){

  // Form creation
  this.myForm = this.fb.group({
    email: [""],
    name: [""],
    password: [""],
  })

  // Each input field will receive it's own context as a simple object:
  public emailContext = {
    controls: {
      formControlName: email, // value to give to the regular [formControlName]
      matInput: true, // true or false if we want apply or not matInput to the input
      required: true, // true or false if we want apply or not the required to the input
      type: "text", // value we want to pass to the regular [type] directive
      placeHolder: $localize`:"@@email:Email"`, // value to pass to the place holder
    }
  }
  public nameContext = {
    controls: {
      formControlName: name,
      matInput: true,
      required: false,
      type: "text",
      placeHolder: $localize`:"@@name:Name"`,
    }
  }
  public passwordContext = {
    controls: {
      formControlName: password,
      matInput: true,
      required: false,
      type: "password",
      placeHolder: $localize`:"@@city:City"`,
    }
  }

That allows me in the html file to write only one ng-template that I will call in a ng-container with the ngTemplateOutlet directive for each input, in which I give the concerned context object with all the needed info about directives for a given form field

<!-- Describes the input template with all binded directives to ts context object-->
<ng-template #inputTemplate let-ctrl="controls">
  <mat-form-field>
    <input [formControlName]="ctrl.formControlName" 
         [matInput]="ctrl.matInput" 
         [required]="ctrl.required" 
         [type]="ctrl.type"
         [placeholder]="ctrl.placeHolder">
  </mat-form-field>
</ng-template>

<ng-container *ngTemplateOutlet="inputTemplate ; context: emailCtx"></ng-container>
<ng-container *ngTemplateOutlet="inputTemplate ; context: nameCtx"></ng-container>
<ng-container *ngTemplateOutlet="inputTemplate ; context: passwordCtx"></ng-container>

Even if I had never seen matInput binded, I found it was elegant to describe a form field in the ts file with the context objects, and then simplify the html file with only one ng-template instead of repeated mat-form-fields. BUT, even if this works well when on regular execution with ng serve then I have an error when I run the ng xi18n (used to edit the xlf files with the placeHolders to translate from ts file).

  1. Is this "allowed" to bind matInput this way, I mean in the same way we apply or not classes with the [class.my-class]="<boolean>"?
  2. Even if this works, I don't understand how the binding makes the difference between [required]="true" which means "apply required directive" and [type]="text" which means "give the "text" value to the type directive". And so, with the context described in the ts file, how could I pass a boolean to a driective, not just telling it to be applied or not like in the [class.my-class]="<boolean>"
  3. How could the binded [matInput] couldn't be a problem on regular serve and cause crash on i18n extraction?
1

There are 1 answers

0
Dano On

In Angular 11 I get the error on property binding of [matInput] even on serve and build. Besides you cannot use mat-form-field element with input without matInput directive.