My code is below, it expects the endpoint to be in the form of an array of items like this [{},{},{}...]
:
[
{
"id": 1,
"name": "item1"
},
{
"id": 1,
"name": "item2"
}
]
But some endpoints use a root node identifier/label like {[{},{},{}...]}
{
"items": [
{
"id": 1,
"name": "item1"
},
{
"id": 1,
"name": "item2"
}
]
}
To handle the latter case, I have added the "startNode" parameter. For example, in the second JSON above, the code expects to pass in "items" as the startNode. I would like to refactor the response observable so that it automatically handles both formats without need to know the startNode:
getEndpoint(event: CustomEvent) {
const mappedValues = mapValuesKeyBy(event.detail, 'name', 'value');
let endpoint = trim(mappedValues._endpoint) || 'http://localhost:4100/states';
const labelKey = trim(mappedValues._labelKey);
const valueKey = trim(mappedValues._valueKey);
const labelFormat = mappedValues._labelFormat;
const hiddenColumns = trim(mappedValues._hiddenColumns);
const startNode = trim(mappedValues._startNode);
this.appService.get(endpoint, {}).subscribe(result => {
if(typeof(result[0]) === 'undefined' && result[startNode]) {
result = result[startNode];
} else {
endpoint = 'http://localhost:4100/states';
}
const titleMap: TitleMapItem[] = map(result, value => ({
name: labelFormat ? this.jsf.parseVariables(labelFormat, value) : value[labelKey],
value: value[valueKey]
}));
this.setTitleMap(event, titleMap);
/** NOTE - remaps the original <mat-select> dynamic list to the Properties <mat-autocomplete> for setting the `defaultValue` */
const tableConfig: AutoCompleteTableConfig = {
labelKey,
valueKey,
hiddenColumns: hiddenColumns || []
};
this.setAutoCompleteList(event, result, tableConfig);
});
}
An example of the first use case endpoint is here: https://jsonplaceholder.typicode.com/users
An example of the second use case endpoint is here: https://dummyjson.com/products
Probably better to properly type your endpoints, but here's how you can do it:
this.appService.get(endpoint, {}).subscribe(result => {
if (!Array.isArray(result)) {
result = Object.values(result)[0];
}
// ...
});
This works by first checking if the result
is an array , and by taking the first object value if it's not.
Of course, this assumes that you only have array and single key objects. Like I said, better to properly type your endpoints.