Link to home
Start Free TrialLog in
Avatar of Dev Me
Dev Me

asked on

JSON array filtering or grouping

I have response object which is a JSON array:

Field:[ 
{
   name: "fieldName1"
   value: "fieldValue1" 
},
{
   name: "fieldName2"
   value: "fieldValue2" 
},
......
]

Open in new window


I have like hundreds of fields like that. I have a need to pass this object to different Angular component and extract out certain fields. Is there a better was to do this in Angular HTML template without having loop through all fields every time I need a particular field in a component? Custom filter pipe will also loop through entire array.
Avatar of ste5an
ste5an
Flag of Germany image

Someone has to loop thru it. But what's wrong with filter?

E.g.

<!DOCTYPE html>
<html>

<body>
    <pre id="debug"></pre>
    <script>
        var obj = {
            Field: [
                { name: "fieldName1", value: "fieldValue1" },
                { name: "fieldName2", value: "fieldValue2" },
                { name: "propertyName4", value: "fieldValue3" }
            ]
        }

        var fieldsOnly = obj.Field.filter(function (item) {
            return (item.name.indexOf('field') >= 0);
        });

        document.getElementById('debug').innerHTML = JSON.stringify(fieldsOnly, null, 1);
    </script>
</body>

</html>

Open in new window


results in

[
 {
  "name": "fieldName1",
  "value": "fieldValue1"
 },
 {
  "name": "fieldName2",
  "value": "fieldValue2"
 }
]

Open in new window

Avatar of Dev Me
Dev Me

ASKER

Thanks for your reply. I have to fetch out certain fields on different level. I am trying to avoid looping all 300 fields every time. I believe filter will do the same (means looping)? I might be wrong
I believe filter will do the same (means looping)? I might be wrong.
Nope. You're not. This "looping" cannot be avoided with your data structure. You can only chose when you do this, to avoid unnecessary ones. Thus my initial comment:

Someone has to loop thru it.
It depends on your Angular design - but the short answer is yes you can pass in parts of your model (although in your case not sure how you would do this - need more info - see below).

Angular good practice suggests that you keep your data (model) in one place and access it through a service. You can create the service yourself using rxjs or you can use Redux to handle the state for you.

The problem I see with your data is that you have no indexes on your items - to find a particular item you have to loop through the array of objects to find it.

Can you give a bit more detail on the use case here -
a) Where does the original data come from
b) When you need to use part of the data in a component - how does that manifest.
Avatar of Dev Me

ASKER


a) Where does the original data come from

app-parent.ts has service call which initializes the root and app-parent.html passes the data to children
app-parent.html
<app-child [fieldArray] = 'root?fieldArray'> <app-child>
<app-another-child [fieldArray]='root?fieldArray'></app-another-child>

Open in new window


app.parent.ts calls parent.service.ts
http.get(){
 return root;
}

Open in new window

Here both app-child and app-another-child, both need need data from the fieldArray. The reason for two different components is they will do different manipulation and display on it.

Not sure if I understood below question:
b) When you need to use part of the data in a component - how does that manifest.
You wrote in you opening post
I have a need to pass this object to different Angular component and extract out certain fields. Is there a better was to do this in Angular HTML template without having loop through all fields every time
I am trying to understand how you need to pass your data - you seem to imply that you only want to pass certain fields to the child - I need to understand what that means in practical terms

Why not structure your components so they feed off the same data service - so you don't have to pass data around through component directives?

Take a look at this answer and see if this is useful for what you want to do
https://www.experts-exchange.com/questions/29103714/Angular-subscribe-and-passing-data-between-components.html?anchorAnswerId=42590619#a42590619
Avatar of Dev Me

ASKER

I believe currently I don't have issue passing data through directive. Even through service could be fine too..I am trying to figure out that "after" passing data is there a better way to extract out the information I need from array other than iterating an array.

JavaScript filter or custom filter will still iterate it through .  My object will have array field and array can contain 100s of fields. But I will need only few fields depending on where I am passing this field array to. I am trying to avoid iterating this array in every component it is being passed to.  But given that each component needs different set of fields, I guess I have no choice?
What other data is there in the array that will allow you to determine what data you want to send to which component? From what I have seen there are none -  so no you are stuck with iterating.

Question: will each component always need to see the same subset of data? If so you could still put it in a service and have the service iterate the first time to build the result and then on subsequent calls return the subset to the component - can't say for sure without more knowledge of your app and how it consumes data.
Avatar of Dev Me

ASKER


What other data is there in the array that will allow you to determine what data you want to send to which component? From what I have seen there are none -  so no you are stuck with iterating.


There will be a GroupType associated with each "name:value" pair in field array. Based on the group-type, respective components will get the data. So yes, I would need to filter per  GroupType.


Question: will each component always need to see the same subset of data?

Most likely so. Since data will be filtered on GroupType whatever set is available in that GroupType per request that's the only data that particular component will need.


 If so you could still put it in a service and have the service iterate the first time to build the result and then on subsequent calls return the subset to the component -

Is this the same service posted above with link?


can't say for sure without more knowledge of your app and how it consumes data.

Yeah, response structure is

parent {
name: fieldname1
value: fieldValue1
.........
 child1 [
 name: fieldname1
  value:fieldvalue1
]
child2[]
child3[]

field [
{
 name:fieldname1
value:fieldvalue1
grouptype:grouptype1
}
}

Open in new window


Not a perfect JSON structure but you will get the gist...so each child has its own component and "field" is divided in multiple components based on the group-type as well based on some field groups (fixed).

so when response comes, I need to filtered out respective data out of child and filed array and pass it to appropriate component. Once with the component , manipulation will happen on that data and will be represented.

Hope I am making sense.
There will be a GroupType associated with each "name:value" pair in field array. Based on the group-type, respective components will get the data. So yes, I would need to filter per  GroupType.
Then I would structure my data by groups
{
   group1:[{
     name: "fieldName1"
     value: "fieldValue1" 
   },
   {
     name: "fieldName2"
     value: "fieldValue2" 
  }],
  group2: [... ]
}

Open in new window

You can then pass the specific grouping to the right component (or have a service return it for you)
If you can't change the data source then in your service - once resolved - do a once off processing of the data into groups that each component needs.

Then, either pass in the group directly using your component variable (root.groupX) or in the child component make a call to the service to return you a specific group.
Avatar of Dev Me

ASKER

Yeah, I guess I will still need to do looping though once I pass the group data to the component. That essentially I am trying to avoid..other option is to transform JSON object to the format I need...

for example...

Transform this :
{
  name: fieldName1
  value: fieldValue1
 },
{
 name: fieldName2
 value:fieldValue2
}

Open in new window


To:
{
  fieldName1:fieldValue1,
  fieldName2:fieldValue2
}

Open in new window


This will avoid me lot of looping.

Any suggestions on if this can be done easily?
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Dev Me

ASKER

Ok thanks. Is there a any library available to do this or I have to write a custom code? Any best practices for this?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Dev Me

ASKER

Thanks Julian/ste5an.