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).
- 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>"
? - 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>"
- How could the binded [matInput] couldn't be a problem on regular serve and cause crash on i18n extraction?
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.