Некоторое время я исследовал, можно ли и как привязать сложную модель к ngModel. Есть статьи, показывающие, как это можно сделать для простых данных (например, строки), таких как это. Но то, что я хочу сделать, более сложное. Допустим, у меня есть класс:
export class MyCoordinates {
longitude: number;
latitude: number;
}
Теперь я собираюсь использовать его в нескольких местах приложения, поэтому я хочу инкапсулировать его в компонент:
<coordinates-form></coordinates-form>
Я также хотел бы передать эту модель компоненту, использующему ngModel, чтобы воспользоваться такими вещами, как угловые формы, но до сих пор безуспешно. Вот пример:
<form #myForm="ngForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name">Name</label>
<input type="text" [(ngModel)]="model.name" name="name">
</div>
<div class="form-group">
<label for="coordinates">Coordinates</label>
<coordinates-form [(ngModel)]="model.coordinates" name="coordinates"></coordinates-form>
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
Действительно ли возможно это сделать или мой подход просто неверен? На данный момент я решил использовать компонент с обычным вводом и выдачей события при изменении, но я чувствую, что это довольно быстро станет беспорядочным.
import {
Component,
Optional,
Inject,
Input,
ViewChild,
} from '@angular/core';
import {
NgModel,
NG_VALUE_ACCESSOR,
} from '@angular/forms';
import { ValueAccessorBase } from '../Base/value-accessor';
import { MyCoordinates } from "app/Models/Coordinates";
@Component({
selector: 'coordinates-form',
template: `
<div>
<label>longitude</label>
<input
type="number"
[(ngModel)]="value.longitude"
/>
<label>latitude</label>
<input
type="number"
[(ngModel)]="value.latitude"
/>
</div>
`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: CoordinatesFormComponent,
multi: true,
}],
})
export class CoordinatesFormComponent extends ValueAccessorBase<MyCoordinates> {
@ViewChild(NgModel) model: NgModel;
constructor() {
super();
}
}
ValueAccessorBase:
import {ControlValueAccessor} from '@angular/forms';
export abstract class ValueAccessorBase<T> implements ControlValueAccessor {
private innerValue: T;
private changed = new Array<(value: T) => void>();
private touched = new Array<() => void>();
get value(): T {
return this.innerValue;
}
set value(value: T) {
if (this.innerValue !== value) {
this.innerValue = value;
this.changed.forEach(f => f(value));
}
}
writeValue(value: T) {
this.innerValue = value;
}
registerOnChange(fn: (value: T) => void) {
this.changed.push(fn);
}
registerOnTouched(fn: () => void) {
this.touched.push(fn);
}
touch() {
this.touched.forEach(f => f());
}
}
Использование:
<form #form="ngForm" (ngSubmit)="onSubmit(form.value)">
<coordinates-form
required
hexadecimal
name="coordinatesModel"
[(ngModel)]="coordinatesModel">
</coordinates-form>
<button type="Submit">Submit</button>
</form>
Я получаю ошибку Cannot read property 'longitude' of undefined
. Для простой модели, такой как строка или число, она работает без проблем.
implements ControlValueAccessor
, если вы это имеете в виду? - person jonrsharpe   schedule 19.05.2017any
, почему бы не попробовать и посмотреть, что произойдет? Не могли бы вы подробнее рассказать о неудачных попытках с помощью минимального воспроизводимого примера? - person jonrsharpe   schedule 19.05.2017