4
My application uses angular-6-json-schema-form to create and manage forms dynamically. Now I would like the select Component, for example have your data coming from some REST source:
My attempts:
Forkjoin: even with forkJoin, the component loads first the data and the component does not work properly.
Viewchild (without *ngIf in the component, of course): as the get HTTP requests have not yet finished, it bursts hundreds of errors that even lock the application, if you use *ngIf, viewChild will always be
undefined
.
Jsonschema
{
"title": "A registration form",
"type": "object",
"required": [
"users"
],
"properties": {
"users": {
"type": "string",
"title": "Usuarios"
},
"todo": {
"type": "string",
"title": "Tarefas"
}
}
}
Uischema/Form:
{
"metadados": {
"ui:widget": "select",
"options": {
"titleMap": [],
"placeholder": "Selecione",
"source": "https://jsonplaceholder.typicode.com/users&field=users",
"columnName": "username",
"columnValue": "id",
"isAuthenticated": false
}
},
"repos": {
"ui:widget": "select",
"options": {
"titleMap": [],
"placeholder": "Selecione",
"source": "https://jsonplaceholder.typicode.com/users&field=todo",
"columnName": "title",
"columnValue": "id",
"isAuthenticated": false
}
}
}
my engine-form.component.ts:
ngOnInit() {
const sub = this.route.paramMap.pipe(
switchMap(params => this.service.geByCTIformItemId(params.get('form_id'), params.get('form_item_id'))),
map(res => {
this.formData = this.loadResource(res);
const uiSchemaObj = JSON.parse(res.ui_schema);
if (this.hasSource(res.ui_schema)) {
const depedencies = this.loadDependenciesFromUiSchema(res.ui_schema);
depedencies.subscribe((dependencyResponse: any) => {
dependencyResponse.map((item: any) => {
const widItem = uiSchemaObj[item.field];
const columnName = widItem.options.columnName;
const columnValue = widItem.options.columnValue;
widItem.options.titleMap = item['data'].map(itemRes => {
return {
value: itemRes[columnValue],
name: itemRes[columnName],
};
});
this.formSchema = {
schema: JSON.parse(res.json_schema),
form: uiSchemaObj,
formData: this.formData,
};
});
});
}
this.formActive = true;
return res;
}),
);
sub.subscribe();
}
private loadResource(res: any) {
const row = {};
if (this.route.snapshot.routeConfig.path !== ':form_id/novo') {
const allowed = Object.keys(res.data).filter(f => !RegExp('^__').test(f));
allowed.forEach(i => {
row[i] = res.data[i];
});
}
return row;
}
private loadDependenciesFromUiSchema(uiSchema: any): Observable<any[]> {
const uiSchemaObj = JSON.parse(uiSchema);
const uiItems = Object.keys(uiSchemaObj).filter(item => !item.includes(':'));
const arr: Observable<any>[] = [];
uiItems.map(uiItem => {
const widItem = uiSchemaObj[uiItem];
if (widItem['ui:widget'] === 'select') {
// tem requisicao dinamica:
if (this.hasValidDynamic(widItem.options)) {
const req = this.http.get(widItem.options.source);
arr.push(req);
}
}
});
return forkJoin(arr);
}
private hasSource(uiSchema: string) {
return uiSchema.includes('source');
}
private hasValidDynamic(options: any): boolean {
return typeof (options.source) !== 'undefined'
&& typeof (options.columnName) !== 'undefined'
&& typeof (options.columnValue) !== 'undefined';
}
engine-form.component.html
<json-schema-form framework="bootstrap-4"
loadExternalAssets="true"
autoUpdateContent="true"
*ngIf="formActive"
[form]="formSchema"
[options]="jsonFormOptions"
(onChanges)="onChanges($event)"
[widgets]="yourNewWidgets">
</json-schema-form>
Wouldn’t it be the case if you put the functions inside the page Onload? type $(Document),ready(Function(){ your routine});
– Marcelo
I think it would be better even using ngIf, in which case the viewchild would also only be available after the data return. 'Cause you need the viewchild?
– Eduardo Vargas
@Eduardovargas, in fact, not precise, were only desperate attempts to try to work.. I just need the component to be loaded only when all requests are complete. When it’s just a component for example, it works, but it’s not the common scenario of my application.
– Samuel Diogo
Make an ajax friend and in Success you put the content.
– Lucas Antonio
Guys, I’m using angle 7..
– Samuel Diogo
@Samueldiogo post after the solution that worked. I found interesting the first 2.
– acacio.martins
already see here Cacio! Thanks!
– Samuel Diogo