import { ChangeDetectionStrategy, Component, effect, forwardRef, input, model, signal, } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MapMessage } from '../../model/proto-message.model'; import { ProtoFieldComponent } from '../proto-field/proto-field.component'; const keyIsEmpty = (key: string | number) => key == null || key === ''; @Component({ selector: 'app-map-field', imports: [ forwardRef(() => ProtoFieldComponent), MatIconModule, MatButtonModule, ], template: `

{{ label() }}

@if(valuePairs()) { @for(value of valuePairs(); track $index) {
} } `, styleUrl: './map-field.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class MapFieldComponent { label = input(); configuration = input.required(); values = model>(); valuePairs = signal([]); private changedInternal = false; constructor() { effect(() => { // TODO: Super hacky but can't really think of another way to keep these in sync // without removing an entry when the key gets blanked. Would need an alternate // design that updated on blur only perhaps if (this.changedInternal) { this.changedInternal = false; return; } const values = this.values(); if (values) { this.valuePairs.set(Object.entries(values)); } }); } add() { const existingValues = this.valuePairs(); if (existingValues) { const newValues = [...existingValues]; newValues.push([undefined, undefined]); this.valuePairs.set(newValues); } else { this.valuePairs.set([[undefined, undefined]]); } } remove(index: number) { const newValues = { ...this.values()! }; const key = this.valuePairs()[index][0]; delete newValues[key]; this.changedInternal = true; this.values.set(newValues); const newValuePairs = [...this.valuePairs()]; newValuePairs.splice(index, 1); this.valuePairs.set(newValuePairs); } updateKey(index: number, key: string | number) { const values = { ...this.values() }; const valuePairs = [...this.valuePairs()]; const pair = [...valuePairs[index]]; if (!keyIsEmpty(pair[0])) { delete values[pair[0]]; } if (!keyIsEmpty(key)) { values[key] = pair[1]; } this.changedInternal = true; this.values.set(values); pair[0] = key; valuePairs[index] = pair; this.valuePairs.set(valuePairs); } updateValue(index: number, value: any) { const valuePairs = [...this.valuePairs()]; const pair = [...valuePairs[index]]; if (!keyIsEmpty(pair[0])) { let existing = { ...this.values()! }; existing[pair[0]] = value; this.changedInternal = true; this.values.set(existing); } pair[1] = value; valuePairs[index] = pair; this.valuePairs.set(valuePairs); } }