В прошлом у меня были проблемы с angular-schema-form-dynamic-select
, и я отказался от него в пользу ванильного решения, которое мне пришлось портировать на angular6-json-schema-form
, когда мы получили зеленый свет для переноса проекта с AngularJS на Angular 7. Хотя для этого требуется немалое количество консистентной смазки, оно позволяет вам заполнять данные или делать что-либо еще при инициализации формы только с формами ванильной схемы.
В моем контексте | async
не было вариантом, потому что по независящим от меня причинам при извлечении данных возвращалось обещание Bluebird, которое несовместимо с асинхронным фильтром. Если у вас нет этого ограничения, я постараюсь проверить, работает ли сначала предложение @Mic.
Я создал помощника для получения результата обещания (в моем случае, конечной точки списка HAL REST) и преобразования его в карту заголовка. В моем случае я всегда хочу, чтобы элемент name
или, в противном случае, его description
, вот с чем я столкнулся:
// returns a [{name: name, value: link}, ...] mapping of items for form
// display based on a promise whose result is a list of entities
private formify(promise) {
return promise
.then(result => result._embedded[Object.keys(result._embedded)[0]].map(element => ({
name: element.name || element.description,
value: element._links.self.href
})))
.catch(error => console.log(error));
}
Затем еще один помощник, который создает обратный вызов onInit
:
// returns an onInit callback for a simple select that is populated with
// the list of entities supplied by the given promise
private getStandardPromiseOnInit(formItem, promise) {
return () => this.formify(promise)
.then(function(result) {
formItem.titleMap = result;
})
.catch(error => console.log(error));
}
Затем я добавляю в элемент формы поле onInit
:
formItem.onInit = this.getStandardPromiseOnInit(formItem, callToRestService());
И после этой обработки мой объект определения формы (он использует синтаксис AngularJS, поскольку это был порт) будет выглядеть примерно так:
[
{
"key": "type",
"placeholder": "...",
"type": "select",
"onInit": <function....>
},
{
"key": "equipment",
"placeholder": "...",
"type": "select",
"onInit": <other function....>
},
...
]
У меня есть служба для получения определений форм, которая выполняет эту работу.
Затем при инициализации компонента формы я рекурсивно просматриваю объявление формы, отыскиваю обратные вызовы onInit и выполняю их:
form: any;
ready: boolean;
ngOnInit() {
...
this.populateForm();
}
populateForm: Function = () => {
let onInits = [];
if (this.form) {
// recursively traverse the form json
let traverse = item => {
if (item.items) {
item.items.map(traverse);
} else if (item.tabs) {
item.tabs.map(traverse);
}
// call onInit callbacks
if (item.onInit) {
onInits.push(item.onInit());
}
};
this.form.map(traverse);
}
Promise.all(onInits)
.then(() => this.ready = true)
.catch(error => {
// error handling and message display
});
};
this.ready
сигнализирует о том, что все обещания были выполнены, поэтому форму можно отобразить без необходимости перерисовки:
<json-schema-form *ngIf="ready"
...
[form]="form"
...
>
</json-schema-form>
Не такой аккуратный, как вставное расширение, но делает свою работу.