I've been beating my head trying to figure out why this parsing error keeps occuring.
Unexpected token [, expected identifier or keyword at column 13 in [zip.errors?.['required']]
I suspect the "?" is a query to the errors array looking for that key. My searches reveal nothing revealing about this "?" syntax. Typescript resources I've seen seem to assume I know how it's defined. I'm happy to be shown a pointer.
Thankfully, the code sample found on https://angular.io/guide/form-validation#validating-input-in-reactive-forms works so it doesn't seem like my Angular libraries are faulty. This is my most simple class and template after following the pattern of the working sample code.
donate.component.ts
import { Component, NgZone, ViewChild, OnInit } from '@angular/core';
import { BackendService } from '../service/backend.service';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
moduleId: module.id,
selector: 'app-donate',
templateUrl: './donate.component.html',
styleUrls: ['./donate.component.scss']
})
export class DonateComponent implements OnInit {
donateForm: FormGroup;
ngOnInit(): void {
this.donateForm = new FormGroup({
name: new FormControl('', [Validators.required]),
zip: new FormControl('', [Validators.required])
});
}
get name() { return this.donateForm.get('name')!; }
get zip() { return this.donateForm.get('zip')!; }
}
donate.component.html
<form [formGroup]="donateForm"#formDir="ngForm">
<div [hidden]="formDir.submitted">
<div >
<label for="zip">Zip code</label>
<input formControlName="zip" name="zip" type="text" id="zip" required>
<div *ngIf="zip.invalid && (zip.dirty || zip.touched)"
>
<div *ngIf="zip.errors?.['required']">Billing zip code is required.</div>
</div>
</div>
</div>
<!-- submit button removed for demo -->
</form>
The first ngIf testing if zip.invalid works so the zip attribute doesn't seem to be the problem. Using zip.errors itself without the query to the errors array compiles but if we aren't looking for a specific type of error then it's not helpful. It seems to balk at my use of the question mark and the array. Since the code example uses that syntax, why is mine breaking?
CodePudding user response:
Since you are using Angular 7, the *ngIf condition in your case should be as:
<div *ngIf="zip.errors?.required">Billing zip code is required.</div>
The ? in zip.errors?.required is referred to as safe navigation operator in Angular that guards against null and undefined values in property paths. Similar concept was introduced in TypeScript 3.7, referred to as Optional Chaining
If zip.errors is null, and we don't use safe navigation operator, then it will cause failure during runtime while trying to read required property on null. ? guards us against such runtime failures.
Unexpected token [, expected identifier or keyword at column 13 in [zip.errors?.['required']]
Using safe navigation operator this (?.['required']) way in template expression is not supported in Angular 7, and hence the error. It's available in newer versions (12.1.0 onwards).
TypeScript 4.2 introduced a new flag noPropertyAccessFromIndexSignature which doesn't allow using the unknown field from Index Signature via 'dot' notation (obj.key), and enforces to use 'indexed' syntax (obj["key"]).
zip.errors?.['required'] makes use of both optional chaining and accessing Index Signature property via indexed syntax.
