Unable to render tree like structure in Angular? - javascript

Hi I am developing web application in Angular 5. I am trying to display tree like structure. I am following the
https://github.com/500tech/angular-tree-component/blob/master/example/cli/src/app/async/async.component.ts and
https://angular2-tree.readme.io/docs/async-data-1
In the above example they have given some data and my application works with it. In real time I am using some other data and converting it to exactly the format in the example they have given.
Below is my example.
let results = JSON.parse('{"userid":"e75792f8-cfea-460e-aca2-07a778c92a7c","tenantid":"00000000-0000-0000-0000-000000000000","username":"karthik","emailaddress":"john#krsars.onmicrosoft.com","isallowed":false,"userroles":[{"userroleid":"b81e63d1-09da-4aa0-af69-0f086ddb20b4","userid":"e75792f8-cfea-460e-aca2-07a778c92a7c","roleid":"85d2f668-f523-4b64-b177-b1a78db74234","tenantappid":1,"validfrom":"2018-01-24T00:00:00","validto":"2018-01-24T00:00:00","isactive":true}]}');
for (const key in results) {
if (results[key] instanceof Array) {
const containerTyp2 = {name: '', hasChildren: false,};
containerTyp2.name = key;
containerTyp2.hasChildren = true;
this.nodes.push(containerTyp2);
} else {
const object = {name: ''};
const containerTyp1 = {name: '', children: []};
object.name = results[key];
containerTyp1.name = key;
containerTyp1.children.push(object);
this.nodes.push(containerTyp1);
}
}
console.log(this.nodes);
Below is the sample data from application example.
this.nodes = [
{
name: 'root1',
children: [
{ name: 'child1' }
]
},
{
name: 'root2',
hasChildren: true
},
{
name: 'root3'
}
];
I am converting my raw data to same format to the example above. When I display both data in console both looks similar except id field. Whenever i display example data, I can see id field get added with random value but explicitly they are not adding. Below is the console of example data.
Below is the console of raw data.
Can someone help me to figure out the issue? I am not able to identify what is the reason not to display raw data. Any help would be appreciated. Thank you.

I fixed this issue by adding below line at the end of for loop.
let results=data;
for (const key in results) {
if (results[key] instanceof Array) {
const containerTyp2 = {name: '', hasChildren: false,};
containerTyp2.name = key;
containerTyp2.hasChildren = true;
this.nodes.push(containerTyp2);
} else {
const object = {name: ''};
const containerTyp1 = {name: '', children: []};
object.name = results[key];
containerTyp1.name = key;
containerTyp1.children.push(object);
this.nodes.push(containerTyp1);
}
this.tree.treeModel.update();

Related

Best practice for writing a facade over JSON object

I've got a JSON file I'm working with. I'll mostly be doing data transformations on the stuff in the data property. I'd like to be able to easily do stuff like .filter to restaurantName and joined without the hassle of delving into the JSON structure each time.
const data = [
{
position: 1,
title: "Queues Near You",
data: [
[
{
restaurantName: "Tonkotsu",
joined: false,
},
{
restaurantName: "BurgerVille",
joined: false,
},
],
],
},
{
position: 2,
title: "Restaurants Near You",
data: [
[
{
restaurantName: "Seoreni",
joined: false,
},
{
restaurantName: "Jinmu",
joined: false,
},
],
],
},
];
So I decided to make a facade toRestaurantArray, that returns an array of arrays out of restaurantName i.e [["Tonkotsu","BurgerVille"], ["Seoreni", "Jinmu"]], that I can use much easier. Then I created a fromRestaurantArray that recreates the JSON structure from this new array.
Am I approaching this problem the right way with the to and from functions? If not, what's a better route, and if I am, how can I refactor the code below in terms of logic (ignore the any types)? I can tell the code in fromRestaurant that just repeatedly loops over the JSOn structure is terrible but am unsure on a better approach.
type RestaurantDetails = {
restaurantName: string;
joined: boolean;
};
type Restaurant = {
position: number;
title: string;
data: Array<Array<RestaurantDetails>>;
};
function* zip(arrayOne: any[], arrayTwo: any[]) {
const len = arrayOne.length;
for (let i = 0; i < len; i++) {
yield [arrayOne[i], arrayTwo[i]];
}
}
// Expected output is to return just the list inside data
const toRestaurantsArray = (initialRestaurantsData: Restaurant[]) => {
const allRestaurantNames: any = [];
for (const eachRestaurantData of initialRestaurantsData) {
const [restaurants] = eachRestaurantData.data;
const restaurantNames = restaurants.map(
({ restaurantName }) => restaurantName
);
allRestaurantNames.push(restaurantNames);
}
return allRestaurantNames;
};
const fromRestaurantsArray = (
restaurantsArray: any[],
initialRestaurantsData: any[]
) => {
const reconstructedRestaurantsData: any = [];
for (const [restaurantNestedArray, eachRestaurantData] of zip(
restaurantsArray,
initialRestaurantsData
)) {
const dataProperty: any = [];
for (const [restaurantName, eachRestaurantsInnerData] of zip(
restaurantNestedArray,
eachRestaurantData.data[0]
)) {
dataProperty.push({
...eachRestaurantsInnerData,
restaurantName: restaurantName,
});
}
const myTotal = { ...eachRestaurantData, data: dataProperty };
reconstructedRestaurantsData.push(myTotal);
}
return reconstructedRestaurantsData;
};
const restoArray = toRestaurantsArray(data);
const filteredArray = restoArray.filter((arr:string[]) => arr.includes("Tonkotsu"))
const reconstructedArray = fromRestaurantsArray(filteredArray, data);
console.log(reconstructedArray)
I cannot offer a direct solution to your question.
JSON formatting notwithstanding, I think what you are attempting to do is similar to what Firebase's query language and other database products do with JSON.
Here's an article entitled Jolt: JSON to JSON Transformation Library.
Not really my area, but my understanding is that these technologies rely on meta data to index the "searchable" parts of a JSON blob. I once had a passing interest in JSON schemas but, so far, haven't had a practical need for implementing one myself.
Your question here reminded me a bit of schemas and made me think about a practical use case for them beyond validation.
(Back in the day, I use to regularly transform XML documents in a similar manner to what you are attempting to do with JSON. There are specialized libraries for transforming XML.)

Mapping data from two dictionary and make a resultant one with specific format in javascript

I have a two dictionaries:
featurePermissionMap = {'2':2,'3':1,'4':1} where key is the feature id and it's value represents the permission type.
Like '2':2 means for a feature id 2 we have a permission 2(Read and Write)
and '3':1 means for a feature id 3 we have a permission 1(Read-Only)
Second Dictionary:
feature_with_sub_feature =
[
{ name: 'FeatureA',
subfeatures: [
{ id: 2, name: 'Feature2' },
{ id: 3, name: 'Feature3' },
},
.......
];
I need a resultant dictionary like below:
read_write_access_feature = {
'read':{},
'write':{}
}
I just want to iterate over feature_with_sub_feature and based on subfeature id, I want output like
read_write_access_feature = {
'read':{'FeatureA':['Feature3',....],......},
'write':{'FeatureA':['Feature2',.....],....}
}
I am trying to achieve this using the two forEach. I am new to javascript.
Any optimized way would be much appreciated.
Any help/suggestions would be much appreciated.
Added function getFeatureWithPermission which will return features with permission passed in parameter. Added code explanation in comment.
call getFeatureWithPermission will required permission as below.
let read_write_access_feature = {
'read': getFeatureWithPermission(1),
'write': getFeatureWithPermission(2)
};
Try it below.
let featurePermissionMap = {'2': 2, '3': 1, '4': 1};
// return features with permission passed in parameter.
function getFeatureWithPermission(permission) {
// use reduce to update & return object as requiment
return feature_with_sub_feature.reduce((a, x) => {
// return object with key as x.name
// value as array of names from subfeatures which have respective permission
// first filter subfeatures for respective permission
// then use map to select only name from subfeatures
a[x.name] = x.subfeatures
.filter(y => featurePermissionMap[y.id] === permission)
.map(y => y.name);
return a;
}, {}); // <- pass empty object as input
}
let feature_with_sub_feature = [{
name: 'FeatureA',
subfeatures: [
{ id: 2, name: 'Feature2' },
{ id: 3, name: 'Feature3' },
]
}];
let read_write_access_feature = {
'read': getFeatureWithPermission(1),
'write': getFeatureWithPermission(2)
};
console.log(read_write_access_feature);

filtering const data in vuejs

i have a vue app with ad group of data.
const data = [
{
name: 'value1',
id: 'id1',
supervisor: true,
},
{
name: 'value2'
id: 'id2',
supervisor: false,
}
]
but i just need to display data for supervisor = true only.
i'd tried to filter it with belows code but it did not work.
const test = data.filter(data => data.supervisor = true);
console.log(test);
can somenone share any reference for me to refer for this filtering function as i new in vue js. or anyone can share their knowledge. because actually i have the data from api which need to be display with some sort of condition.
i have tried using url/api/items?supervisor=true and then i was inform that the API did no support for that kind of way so i need to create a filter function in javascript from data that retrieve from APIs. i'm using above const data =[{...,...}] in this question for it easier to understand.
const test = data.filter(data => data.supervisor === true);
Full working example, since your data was also missing a comma, so the not working part can be from there:
const data = [
{
name: 'value1',
id: 'id1',
supervisor: true,
},
{
name: 'value2',
id: 'id2',
supervisor: false,
}
];
const test = data.filter(data => data.supervisor === true);
console.log(test);
You should use const test = data.filter(data => data.supervisor); instead of > true

Getting an empty array while trying to return an array of JSON documents using REST extension (MarkLogic)

function get(context, params) {
var max = "http://blahblah"; //declaring namespace
let query = []
if (params.tokenNum) {
query.push(cts.elementValueQuery(fn.QName(max, "TOKENUM"), params.tokenNum))
query.push(cts.collectionQuery("WORKORDER"))
}
if (params.location) {
query.push(cts.elementValueQuery(fn.QName(max, "LOC"), params.location))
query.push(cts.collectionQuery("WORKORDER"))
}
if (params.Id) {
query.push(cts.elementValueQuery(fn.QName(max, "ID"), params.Id))
query.push(cts.collectionQuery("WORKORDER"))
}
let result = []
let doc = fn.subsequence(cts.search(cts.andQuery(query)), params.start, params.length)
const json = require('/MarkLogic/json/json.xqy');
let config = json.config("custom");
for (var d of doc) {
result.push(json.transformToJson(d, config));
}
return result
};
I am trying to return an array of JSON documents using REST extension but all I am getting is an empty array I am using the URL
http://localhost:9015/v1/resources/location?rs:Id=ABC&rs:start=1&rs:length=10
However when I run this code in the query console by using a params object as a test like this
let params = {
start: '1',
length: '10',
tokenNum: "100404",
location: "0256",
Id: "ABC"
};
then I get what I am looking for(which is the array of JSON documents).
I can't figure it out what's going wrong. I would appreciate if someone can help

Destructing and/or mass assigning in ES6

I have 2 sources of data. One of the sources is the "template" to what is acceptable for the data. However, the second source may have a large amount of data that I don't care about (100+ properties in the JSON). Here are the schemas:
// Only store the data we care about. Only a small subset of
// data that I need for this particular dataset.
state = {
isDirty: false,
data: {
name: '',
address: '',
city: '',
state: ''
}
}
The second source will have the 4 attributes in the data schema above (plus many many more I don't care about). Currently, I am assigning them like this:
let updatedData = {};
for(const key in this.state.data) {
updatedData[key] = someDataSource[key];
}
this.state.data = updatedData;
Using ES6, and perhaps destructing, is there a better way to mass assign variables like this?
Thanks again!
EDIT
Added for clarification the assignment after the loop.
Lodash pick can be used to pick specific keys, or helper function can be used for same purpose:
const pick = (obj, keys) => Object.keys(obj)
.filter((key) => keys.indexOf(key) >= 0)
.reduce(
(newObj, key) => Object.assign(newObj, { [key]: obj[key] }),
{}
);
This is already suggested in many related questions. The thing that is specific to this question is:
this.state.data = pick(someDataSource, Object.keys(this.state.data));
Properties can be excluded and modified in the JSON.parse reviver :
var o = JSON.parse('{"a":1, "b":2}', (k, v) => k === 'a' ? void 0 : k === 'b' ? 3 : v)
console.log( o )
A trick you can do (trick because it requires to swallow an error) is to use an non extensible object, using the Object.preventExtensions and then use Object.assign to fill it with data (in a try/catch block).
// Only store the data we care about. Only a small subset of
// data that I need for this particular dataset.
state = {
isDirty: false,
data: {
name: '',
address: '',
city: '',
state: ''
}
}
const newData = {
name:'name',
address:'address',
city:'city',
state:'state',
phone:'phone',
zip:'zip'
}
const updatedData = Object.preventExtensions({...state.data});
try{
Object.assign(updatedData, newData);
} catch(throwaway){};
console.log(updatedData);
And as a function for reuse
function schemaMerge(schema, data) {
const mergedData = Object.preventExtensions({...schema});
try {
Object.assign(mergedData, data);
} catch (throwaway) {};
return ({...mergedData}); // create a new object from the merged one so that it no longer is extensionless
}
// Only store the data we care about. Only a small subset of
// data that I need for this particular dataset.
state = {
isDirty: false,
data: {
name: '',
address: '',
city: '',
state: ''
}
}
const newData = {
name: 'name',
address: 'address',
city: 'city',
state: 'state',
phone: 'phone',
zip: 'zip'
}
const updatedData = schemaMerge(state.data, newData);
state.data = updatedData;
console.log(state.data);

Categories

Resources