Body
Body

Reputation: 3688

Get value from child Array with a given ID

I have the following Array and I'm trying to print the child array value using .find by providing an ID

connections = [
    {
      group: 'a',
      items: [
        {
          id: '1',
          name: 'Andre'
        },
        {
          id: '2',
          name: 'David'
        }
      ]
    },
    {
      group: 'b',
      items: [
        {
          id: '3',
          name: 'Brandon'
        }
      ]
    },
]

I have tried the following in my Angular app,

getUser(id) {
    this.activeItem = this.connections.items.find(data => data.id === id);
    console.log(this.activeItem);
}

I'm providing the correct ID but I'm getting an error saying,

error TS2339: Property 'items' does not exist on type....

Thank you.

Upvotes: 2

Views: 1057

Answers (9)

StepUp
StepUp

Reputation: 38114

You can use filter and some methods. This approach will filter array and your array will contain only desired items:

let connections = [
    {
      group: 'a',
      items: [
        {
          id: '1', name: 'Andre'
        },
        {
          id: '2', name: 'David'
        }
      ]
    },
    {
      group: 'b',
      items: [
        {
          id: '3', name: 'Brandon'
        }
      ]
    },
]

let id = 3;
// ONE WAY
const result = connections.filter(f=> f.items.some(s=> s.id == id))
                          .flatMap(fm => fm.items);
console.log(`result: `, result);

// OR ANOTHER WAY:
const resultWithGroup = connections.filter(f=> f.items.some(s=> s.id == id));
const resultItem = Object.assign({}, ...resultWithGroup).items.find(f => f.id == id);
console.log(`resultItem: `, resultItem);
console.log(`resultItem as an array: `, [resultItem]);

In addition, it is possible to use flatMap method. By using this approach you are getting all items with desired id and then find the first element with id == 3:

let connections = [
    {
      group: 'a',
      items: [
        {
          id: '1', name: 'Andre'
        },
        {
          id: '2', name: 'David'
        }
      ]
    },
    {
      group: 'b',
      items: [
        {
          id: '3', name: 'Brandon'
        }
      ]
    },
]

const result = connections.flatMap(f => f.items).find(f => f.id == id);
console.log(`result as array`, [result]);

Upvotes: 2

David ROSEY
David ROSEY

Reputation: 1805

It is normal that you get this error: "error TS2339: Property 'items' does not exist on type....". Actually, 'connections' is an array and does not have any prperty 'items'. 'items' is an attribut of the elements contained in 'connections' array.

You can try something like:

getUser(id) {
    for (const element of this.connections) {
      this.activeItem = element.items.find(data => data.id === id);
      if (this.activeItem) {
          break;
      }
    }
    console.log(this.activeItem);
}

Once 'this.activeItem' is found we exit the loop with the 'break;' statement.

Upvotes: 0

Adrita Sharma
Adrita Sharma

Reputation: 22213

You can use flatMap

Try like this:

getUser(id) {
  this.activeItem = this.connections.flatMap(x => x.items).find(data => data.id === id);
  console.log(this.activeItem);
}

Working Demo

Upvotes: 2

Jeet Prakash
Jeet Prakash

Reputation: 643

As i can see from the Json object, the items arrays are grouped inside their parent objects. So first you would have to flatten the grouped array:

let items = []
connections.forEach(obj => obj.items.forEach( item => items.push(item)))

Now the items array would only be item objects so it will be easier to do a find:

items.find(item => item.id == 3)

Upvotes: 1

Amir Christian
Amir Christian

Reputation: 595

Try this. (You made mistake with connections.items)

getUser(id) {
    let activeItemIndex = -1;
    this.connections.forEach((c) => {
      activeItemIndex = c.items.findIndex(item => item.id === id);
      if (activeItemIndex > -1) {
        this.activeItem = c.items[activeItemIndex];
      }
    });
}

Upvotes: 0

Bahador Raghibizadeh
Bahador Raghibizadeh

Reputation: 1265

You have to specify index of connections.

But this is the better solution, Because you have all the users in one place:

getUser(id) {
    users = connections.reduce((users, item)=>{
        users.push(...item.items);
        return users;
    }, []);
    this.activeItem = users.find(data => data.id === id);
    console.log(this.activeItem);
}

Upvotes: -1

Prashant SINGH SENGAR
Prashant SINGH SENGAR

Reputation: 137

connections variable is an array and you are trying to access it as an object. PFB the below code it should be working fine for you.

    getUser(id) {
        this.activeItem = connections.find(function(element) {  return element.items.find(function(el){return el.id==id;}); });
        console.log(this.activeItem); 
}

Upvotes: 0

Tanish
Tanish

Reputation: 59

The reason your "this.connections.items.find" is not working is that connections variable here represents an array of objects, you cannot directly access a key that is inside an objects contained in an array of objects.

Use this code instead:

this.activeItem = this.connections.filter(obj => obj.items.find(val => val.id == id));
console.log(this.activeItem.items);

Upvotes: 0

The Fabio
The Fabio

Reputation: 6250

You are trying to use an array without specifying the element of the array

-----------------\/ here
this.connections[0].items.find(data => data.id === id); 

Upvotes: 0

Related Questions