1

I'm creating an option selector, were you're able to select options for a certain machine. See image with a design of the objects:

Object:

enter image description here

Code:

export class Machine{
    Id: string;
    MachineGroup: MachineGroup;
    Price: number;
    Description: string;
    Image: Image;
    Weight: number;
    Power: number;
    Speed: number;
    Name: string;
    BomId: number;
    Options: Option[];
}

export class Option{
    Id: number;
    Price: number;
    OptionGroup: OptionGroup;
    Description: string;
}

export class OptionGroup{
    Id: number;
    Image: Image;
    Name: string;
}

The options need to be sorted under their OptionGroup, is there some kind of LINQ I can use within Angular?

I mean I can make a function within the component which loops though the list of options and add those objects to a new list to show. But this gave an undefined error, while the component isn't rendered before the Machine is set. The console.log printed the object like it supposed to be. The error is literally: "this is undefined", so I expect the OptionGroup array.

Rendered if machine is set:

<div *ngIf="machine">
    <app-option-selector [inputMachine]="machine"></app-option-selector>
</div>

Component with function:

export class OptionSelectorComponent implements OnInit {

  @Input() inputMachine: Machine;
  options: Option[];
  optionGroups: OptionGroup[];

  constructor() { }

  ngOnInit() {
    this.options = this.inputMachine.Options;
    this.setOptionGroups();

  }

  setOptionGroups(){
    this.options.forEach(function(e){
      console.log(e.OptionGroup);
      this.optionGroups.push(new OptionGroup())
    })
  }
}

So is there an Angular way to create such sorting? Not prone to errors, like I tried to do?

5
  • 1
    Use the sort function Commented Jul 16, 2019 at 6:50
  • this gave an undefined error,: which has nothing to do with Angular. You're trying to push option groups into this.optionGroups, but you never initialized this.optionGroups, so it's undefined. Commented Jul 16, 2019 at 6:52
  • optionGroups: OptionGroup[] = []; is initialization right? But it gives the same error. Commented Jul 16, 2019 at 6:54
  • And the error is? And the line that the error points to is? Commented Jul 16, 2019 at 6:58
  • 3
    I guess you’re in another scope in the forEach loop, so you can’t use this. You should use an arrow function instead inside forEach. Commented Jul 16, 2019 at 6:59

3 Answers 3

1
 ngOnInit() {
    this.options = this.inputMachine.Options;
    this.optionGroups = this.setOptionGroups();
  }

setOptionGroups() {
  const optionsCopy = [...options]; // don't mutate options array
  this.optionsCopy.sort((a, b) => (
    // your sort logic
    a.Id - b.Id // example : order by id
  ));
  return optionsCopy.map(option => new OptionGroup() {
    id: option.Id
  });
}
Sign up to request clarification or add additional context in comments.

3 Comments

What does the map function do in the end?
Map documentation : it returns a new array. We use it to create an array of OptionGroup from optionsCopy which is an array of Option.
Okay thanks for your help and time! I'm going to make a combination of the posts and will make an update with answer to this question by today.
1

You can group by attribute:

arrayToObject(array, keyField) {
    return array.reduce((obj, item) => {
        obj[item[keyField]] = item;
        return obj;
    }, {});
}

Usage:

const groups = this.arrayToObject(this.options, 'OptionGroup');
       this.optionGroups = Object.values(groups); 

1 Comment

Thanks for your help and time this is almost the function I needed, I'm going to make a combination of the answer posts and will update the answer by today.
1

You could use lodash

    const machines: Machine[] = [/*...*/];
    const options: Option[][] = machines.map(machine => machine.options);
    const flatOptions: Option[] = [].concat(...options); // could also use lodash flatten
    const optionGroups: OptionGroup[] = flatOptions.map(option => option.optionGroup); 
    const uniqueOptionGroups: OptionGroup[] = _.uniq(optionGroups); // import * as _ from 'lodash'

And for the sort itself

machines.forEach(machine =>
      machine.options.sort((option1, option2) =>
        // your compare
      );
    );

2 Comments

Thanks I've read some documentation of Lodash, seems like an interesting library! Definitely going to try it out.
Yeah it serves some interesting utility. You don't need to to learn it. Just in case you want to write some util functions in your application just check if there is the same util available in lodash. It mostly is.

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.