Я хочу создать настраиваемый элемент управления, содержащий другие настраиваемые элементы управления, и использовать ngModel, который их всех соединяет. Нравиться :
PersonSearchComponent:
- DeveloperSearchControl
- Name - some string input
- Фамилия
- ProffesionSelect - настраиваемый элемент управления, ожидающий ProffesionModel
- BuildingSearchControl
- Some custom controls here
- CountryCustomControl - настраиваемый элемент управления, ожидающий CountryModel
- PersonListComponent: -импортированные данные об элементах из PersonSearchComponent какой-либо службой
- SomeOtherSearchComponent
- DeveloperSearchControl - reusable
Итак, пока у меня есть рабочая версия, но я думаю, что сделал что-то плохое (возможно, мне стоит использовать FormBuilder):
Шаблон PersonSearch:
<div>
<developer-search-control [(ngModel)]="searchModel.developerSearchModel"></developer-search-control>
<building-search-control [(ngModel)]="searchModel.buildingSearchModel"></building-search-control>
<country-select [(ngModel)]="searchModel.countryModel"><country-select>
</div>
ParentSearch component
...
export class PersonSearch {
@Output() searchDataEmitter= new EventEmitter();//Exports data to above component which contains this, and listComponent
searchModel : PersonSearchModel : new PersonSearchModel();
performSearch()
{
//gets data from service with searchModel and searchDataEmitter transpors it to above component
}
}
Модели: PersonSearchModel:
developerSearchModel : DeveloperSearchModel = new DeveloperSearchModel();
buildingSearchModel: BuildingSearchModel = new BuildingSearchModel();
countryModel : CountryModel;
DeveloperSearchModel:
name : string
surname : string
proffesion : ProfessionModel
Шаблон developerSearchControl.component.html:
<div *ngIf="value">//This is the problem
<input [(ngModel)]="value.name"></input>
<input [(ngModel)]="value.surname"></input>
<profesion-select [(ngModel)]="value.ProffesionSelect">
</div>
developerSearchControl.component:
...
@Component({
selector: 'developer-search-control',
templateUrl: './developerSearchControl.component.html',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DeveloperSearchControlComponent),
multi: true,
}],
})
export class DeveloperSearchControlComponent extends ElementBase<DeveloperSearchModel > {
protected model: NgModel;
constructor(
@Optional() @Inject(NG_VALIDATORS) validators: Array<any>,
@Optional() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<any>,
) {
super(validators, asyncValidators);
}
}
profesionSelect.component
...
@Component({
selector: 'profesion-select',
template: `
<div>
<label *ngIf="label">{{label}}</label>
<dx-select-box
[dataSource]="data"
[(ngModel)]="value"
displayExpr="proffesionName"
[placeholder]="placeholder"
[searchEnabled]="true"
>
</dx-select-box>
</div>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: ProfessionComponent,
multi: true,
}],
})
export class ProfessionComponent extends ElementBase<string> implements OnInit {
private data: ProfessionModel[];
private label: string = 'proffesion :';
private placeholder: string = 'Select profession';
@ViewChild(NgModel) model: NgModel;
constructor(private proffesionService: ProfessionDataService,
@Optional() @Inject(NG_VALIDATORS) validators: Array<any>,
@Optional() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<any>,
) {
super(validators, asyncValidators);
}
ngOnInit() {
this.professionService.getDevelopersProfessions().subscribe(
data => {
this.data = data;
}
);
}
}
ElementBase - это общий ControlValueAccessor с проверкой из: http://blog.rangle.io/angular-2-ngmodel-and-custom-form-components/
Итак, моя проблема в том, что когда я создаю шаблон для детей (developerSearch, buildingSearch), значение, переданное с помощью ngModel, не инициализируется для них, и я получаю:
EXCEPTION: Uncaught (in promise): Error: Error in ./DeveloperSearchControlComponent class DeveloperSearchControlComponent - inline template:2:33 caused by: Cannot read property 'name' of null
Error: Error in ./DeveloperSearchControlComponent class DeveloperSearchControlComponent - inline template:2:33 caused by: Cannot read property 'name' of null
Поскольку значение из ngModel при запуске равно нулю. Поэтому я должен использовать * ngFor = "value" в шаблонах дочерних компонентов, что выглядит плохо. Есть ли решение для инициализации объекта перед проверкой шаблона? или я делаю это очень неправильно?
<input [(ngModel)]="value?.name"></input>
. По крайней мере, это подавит исключение. - person mickdev   schedule 07.03.2017[(ngModel)]
;) - person AJT82   schedule 07.03.2017?.
, вам нужно разделить его на[ngModel]="foo?.bar" (ngModelChange)="foo && foo.bar = $event"
- person Günter Zöchbauer   schedule 08.03.2017