Search code examples
javascriptarraysangulartypescriptprototype

Why are Array Prototype functions not working within an other array function like for each?


I have the following issue I need to fetch some values from a other array while iterating.

But within the for each operation, the Array loses all its prototype functions.


const allCrumbs: BreadCrumb[] = this.createBreadcrumbs(this.activatedRoute.root);

last.url.split('/').forEach((segment: string) => {
            if (segment !== '#') {
                // This is the part that doesn work within the array
    // Edit forgot null check here 
                const label = allCrumbs.find(value => value.url.endsWith(segment)).label;
                // allCrumbs.find(...) is not defined

                this.breadCrumbs.push({label: label ? label : segment, url: `/${segment}`});
            }
        });
    // This works just fine
    const testlabel = allCrumbs.find(value => value.url.endsWith('test')).label;

when I do this, the error:

allCrumbs.find(...) is not defined

appeard.

When I do the same outside the scope of the Other array, it works fine.

Can someone explain this behaviour ? And maybe give a hint to a solution.

Thank you very much:

Solution

Forgot a nullcheck, thank you .

this works now

last.url.split('/').forEach((segment: string) => {
            if (segment !== '#') {

                const result = allCrumbs.find(value => value.url.endsWith(segment));

                this.breadCrumbs.push({label: result ? result.label : segment, url: `/${segment}`});
            }
        });

Shame on me. But Thank you all for you Patience


Solution

  • The problem is that your .find() is not finding anything based on your predicate. So it returns undefined.

    Instead, expect that it might return undefined and handle accordingly. Attempt to find the matching value first:

    const crumb = allCrumbs.find(value => value.url.endsWith(segment));
    

    And then depending on which version of Angular (and therefore Typescript) you are using, you can either using optional chaining or a ternary expression to get the label.

    Angular >= v9

    const label = crumb?.label;
    

    Angular < v9

    const label = crumb ? crumb.label : '';
    
    const allCrumbs: BreadCrumb[] = this.createBreadcrumbs(this.activatedRoute.root);
    
    last.url.split('/').forEach((segment: string) => {
      if (segment !== '#') {
        const crumb = allCrumbs.find(value => value.url.endsWith(segment));
        const label = crumb ? crumb.label : '';
        this.breadCrumbs.push({
          label: label ? label : segment, 
          url: `/${segment}`
        });
      }
    });