2

I have the following array. I am using this array to dynamically produce checkboxes on my UI. This is being used to save user config as to what they will be able to see in a nav menu.

  accessLevels: any = [
    {
      description: "Properties",
      type: '1',
      selected: false
    },
    {
      description: "Equipment",
      type: '2',
      selected: false
    },
    {
      description: "Jobs",
      type: '3',
      selected: false
    },
    {
      description: "Calender",
      type: '4',
      selected: false
    }
]

I am making a call to an API which returns me an array of the users config. So what I will get is an array of the pages and their type like this:

    {
      description: "Equipment",
      type: '2'
    },
    {
      description: "Jobs",
      type: '3'
    }

In the array returned from the API I am just getting the values that should appear checked on the check boxes so what I want to do is loop through the returned array and check if any of the types match any types in the checkbox array if they do I want to set 'selected' to true. Thus checking the checkbox.

Here is what I have so far:


  async loadLandlordConfig(key: string) {

    const result = await this.userService.loadLandlordConfig(key);

    //let accessLevels = [];

    this.selectedApiValues = result[0].accessLevels;

    this.selectedApiValues.forEach((selectedValue)=> {

    });
  }

Im not sure how to cross check the values and then change selected to true.

Hope I have made everything clear enough. Any questions please ask. All help appreciated.

4
  • How are you matching objects across arrays? Some array items have "value", some have "type". Commented Feb 25, 2020 at 14:11
  • @KurtHamilton Apologies I was just typing the arrays into the there and missed that, my mistake. I have adjusted accordingly Commented Feb 25, 2020 at 14:13
  • So you're matching on type? Commented Feb 25, 2020 at 14:13
  • Yes that's correct. Commented Feb 25, 2020 at 14:13

5 Answers 5

4

For small arrays

You can check for the existence within a filter using some:

const intersect = this.array1.filter(a1 => 
  this.array2.some(a2 => a1.type === a2.type));

The problem with this is that you are doing multiple loops through array 2.

For larger arrays

To keep your loops to a constant number, you could create a map of one of your arrays, and check that within a filter of the other array:

const map2 = new Map(this.array2.map(x => [x.type, s]));
const intersect = this.array1.filter(a1 => 
  map.has(a1.type));

This adds a little bit of complexity, but is more efficient for all but the simplest cases.

Sign up to request clarification or add additional context in comments.

Comments

2
  const accessLevels: any[] = [
    {
      description: 'Properties',
      type: '1',
      selected: false
    },
    {
      description: 'Equipment',
      type: '2',
      selected: false
    },
    {
      description: 'Jobs',
      type: '3',
      selected: false
    },
    {
      description: 'Calender',
      type: '4',
      selected: false
    }];

  const results: any[] = [
    {
      description: 'Equipment',
      type: '2'
    },
    {
      description: 'Jobs',
      type: '3'
    }];

  accessLevels.forEach(accessLevel => {
    accessLevel.selected = results.some(x => x.type === accessLevel.type); });

Comments

2

You can achieve what you want with the following simple example :

let accessLevels = [
    {
      description: "Properties",
      type: '1',
      selected: false
    },
    {
      description: "Equipment",
      type: '2',
      selected: false
    },
    {
      description: "Jobs",
      type: '3',
      selected: false
    },
    {
      description: "Calender",
      value: '4',
      selected: false
    }
]

let api = [
    {
      description: "Equipment",
      type: '2'
    },
    {
      description: "Jobs",
      value: '3'
    }
];

for(var i = 0; i < accessLevels.length; i++) {
     accessLevels[i].selected = api.find(e => e.description === accessLevels[i].description) ? true : false;
}

console.log(accessLevels);

2 Comments

Is there a reason why you iterate with a for instead of a .forEach ? Also a .find looks preferable in my point of view as it stops and return as soon as it gets a value as far as I know.
Thanks for the note, I updated my answer but keep in mind as long as you can solve the problem at hand, for loop is faster than forEach. Solve first, refactor later!
0

You can use Map collection to have O(1) while mapping the second array:

const unique = new Map(received.map(s => [s.description, s]));
const result = accessLevels.map(({ description, type})=> 
    ({selected: (unique.get(description) ? true : false), type, description}))

An example:

let accessLevels = [
  {
    description: "Properties",
    type: '1',
    selected: false
  },
  {
    description: "Equipment",
    type: '2',
    selected: false
  },
  {
    description: "Jobs",
    type: '3',
    selected: false
  },
  {
    description: "Calender",
    type: '4',
    selected: false
  }
]

const received = [
  {
  description: "Equipment",
  type: '2'
  },
  {
    description: "Jobs",
    value: '3'
  }
];

const unique = new Map(received.map(s => [s.description, s]));
const result = accessLevels.map(({ description, type})=> 
    ({selected: (unique.get(description) ? true : false), type, description}))
console.log(result);

Comments

0

I've made some changes to your code. Here's how it looks like:

async loadLandlordConfig(key: string) {

    const result = await this.userService.loadLandlordConfig(key);

    // assuming there's always a result.
    // ACCESS_LEVELS is the list of your config.
    accessLevels = result[0].accessLevels;
    this.selectedApiValues = ACCESS_LEVELS.map((al: any) => {
      const selected = accessLevels.findIndex(a => a.type === al.type) > -1;
      return { ...al, selected }
    })
  }

This will give you with the value

this.selectedApiValues = [
  {
      description: "Properties",
      type: '1',
      selected: false
    },
    {
      description: "Equipment",
      type: '2',
      selected: true
    },
    {
      description: "Jobs",
      type: '3',
      selected: true
    },
    {
      description: "Calender",
      type: '4',
      selected: false
    }
]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.