Using Angular 17, I work through Matt Thornfield's video series of real site with Angular. An enum shall render its value on template, but typescript does not compile it. I read https://stackblogger.com/no-index-signature-found/. But how is this applied on component template? I tried that for 3 hours, but I failed miserably.
compiler error messager:
X [ERROR] NG3: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof Layout'. No index signature with a parameter of type 'string' was found on type 'typeof Layout'. [plugin angular-compiler]
src/app/admin/rooms/room-edit/room-edit.component.html:19:36:
19 │ <label for="layout{{layout}}">{{layoutEnum[layout]}}</label>
╵ ~~~~~~~~~~~~~~~~~~
Error occurs in the template of component RoomEditComponent.
src/app/admin/rooms/room-edit/room-edit.component.ts:7:15:
7 │ templateUrl: './room-edit.component.html',
Layout.ts
export enum Layout {
THEATER = "Theater",
USHAPE = "U-Shape",
BOARD = "Board Meeting"
}
room-edit.component.ts:
import { Component, Input, OnInit } from '@angular/core';
import { Layout, Room } from '../../../model/room';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-room-edit',
templateUrl: './room-edit.component.html',
styleUrl: './room-edit.component.css'
})
export class RoomEditComponent implements OnInit{
@Input() room: Room;
layouts = Object.keys(Layout);
layoutEnum = Layout;
roomForm = new FormGroup(
{
roomName : new FormControl('roomName'),
location: new FormControl('location')
}
);
constructor() {
this.room = new Room();
}
ngOnInit(): void {
this.roomForm.patchValue({
roomName: this.room.name,
location: this.room.location
});
}
onSubmit() {
this.room.name = this.roomForm.controls['roomName'].value ?? '';
this.room.location = this.roomForm.value['location'] ?? '';
console.log(this.room);
}
}
room-edit.component.html:
<h1> {{room.id == null ? 'Add' : 'Edit'}} Room</h1>
<form [formGroup]="roomForm">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" placeholder="room name" formControlName="roomName" >
<div class="alert alert-danger"></div>
</div>
<div class="form-group">
<label for="location">Location</label>
<input type="text" class="form-control" id="location" placeholder="location" formControlName="location" >
<div class="alert alert-danger"></div>
</div>
<h2>This room can accomodate:</h2>
<div class="form-group" *ngFor="let layout of layouts">
<label for="layout{{layout}}">{{layoutEnum[layout]}}</label>
<input type="number" class="form-control" id="layout{{layout}}" formControlName="layout{{layout}}">
</div>
<!-- list the layout types here -->
<button type="button" class="btn btn-primary" (click)="onSubmit()" >Save</button>
</form>
Let's try to move the layout fetch based on the key to the RoomEditComponent.
RoomEditComponent - add new method:
getLayoutByKey(layoutKey: string): Layout {
return this.layoutEnum[layoutKey as keyof typeof Layout]
}
room-edit.component.html - change line:
<label for="layout{{layout}}">{{layoutEnum[layout]}}</label>
to:
<label for="layout{{layout}}">{{ getLayoutByKey(layout) }}</label>