#angular #angular-material #jsonschema
#angular #angular-материал #jsonschema
Вопрос:
Я использую форму схемы Angular6 JSON
Где html-элемент select описывается с помощью json, как показано ниже:
{
"schema": {
"type": "object",
"title": "My Form",
"properties": {
"select1552420741389": {
"type": "string"
}
},
"required": [
"select1552420741389"
]
},
"layout": [
{
"key": "select1552420741389",
"type": "select",
"multiple": false,
"notitle": false,
"title": "Select",
"titleMap": [
{
"name": "Option 1",
"value": "option1"
},
{
"name": "Option 2",
"value": "option2"
}
]
}
],
"data": {}
}
И я хотел бы иметь возможность динамически загружать карту заголовков с помощью пользовательской функции обратного вызова или указывать URL-адрес для вызова, чтобы получить данные карты заголовков.
Я видел падение библиотек, написанных на angular.js но мне нужно решение, которое работает для Angular и Material.
Любые предложения приветствуются!
Ответ №1:
В прошлом у меня были проблемы с angular-schema-form-dynamic-select
, и я отказался от этого в пользу ванильного решения, которое затем мне пришлось перенести на angular6-json-schema-form
, когда мы получили зеленый свет для переноса проекта с AngularJS на Angular 7. Хотя для этого требуется довольно много усилий, это позволяет вам заполнять данные или делать все, что вы хотите при инициализации формы, используя только формы ванильной схемы.
В моем контексте | async
это было невозможно, потому что по независящим от меня причинам выборка данных вернула обещание bluebird, которое несовместимо с асинхронным фильтром. Если у вас нет этого ограничения, я бы попробовал сначала посмотреть, сработает ли предложение @Mic.
Я создал помощник для получения результата promise (в моем случае, конечной точки списка 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 = resu<
})
.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>
Не так аккуратно, как выпадающее расширение, но выполняет свою работу.
Ответ №2:
Я не пробовал это сам, но из readme видно, что привязка к [layout]="yourJsonFormLayout"
атрибуту с yourJsonFormLayout
обновлением по вашему требованию будет работать.
Вы также можете использовать | async
канал для загрузки данных с запрашиваемого URL-адреса, настраивая формат, как в
this.yourJsonFormLayout = http.get(...).pipe(map(...format your object...));