1

I am trying to dynamically build an array for linkObjects. Dynamically because I need to read the Ngrx Store and get parameters. like in the heatmap

public linksObject = [
    {
        name: 'Consumption',
        link: ['../consumption'],
    },
    {
        name: 'Heatmap',
        link: ['../heatmap&res=foo'],
    }
 ];
 

I have a switchMap that builds out the individual objects, but I need to append it to this.linkObjects

the second switchMap is getting an array of roles like ['admin', 'test', 'field_engineer'] and inside getLinkObjects it is building the object:

{name: label, link:['..\ ...']}

pages is just a static list of labels ['consumption', 'heatmap']

    public getLinkObjects(roles: string[]): Observable<any> {
        return from(this.pages).pipe(
            switchMap(
                (page): Observable<ILinksObject> =>
                    from(roles).pipe(
                        map((role) => ({
                            name: page,
                            link: [`../${page}&role=${role}`],
                        })),
                    ),
            ),
        );
    }
this.fetchRoles()
    .pipe(
        switchMap((roles: IUserSite[]) => this.getCurrentRoles(roles)),
        switchMap((role: string[]) => this.getLinkObjects(role)),
        // concat the objects emitted by switchMap
    )
    .subscribe();

I tried the following 3 ways, that didn't work:

  • adding a push in the subscribe
  • adding a tap
this.fetchRoles()
    .pipe(
        switchMap((roles: IUserSite[]) => this.getCurrentRoles(roles)),
        switchMap((role: string[]) => this.getLinkObjects(role)),
        // concat the objects emitted by switchMap
    )
    .subscribe(this.linkObjects.push);
this.fetchRoles()
    .pipe(
        switchMap((roles: IUserSite[]) => this.getCurrentRoles(roles)),
        switchMap((role: string[]) => this.getLinkObjects(role)),
        tap((role) => this.linkObjects.push(role))
        // concat the objects emitted by switchMap
    )
    .subscribe();
        this.fetchRoles()
            .pipe(
                switchMap((roles: IUserSite[]) => this.getCurrentRoles(roles)),
                switchMap((role: string[]) => this.getLinkObjects(role)),
                tap(console.log), // this gets printed
                reduce((acc, role) => acc.concat(role), this.linksObject),
                tap(console.log), // this does not get printed
            )
            .subscribe(console.log);

I need help to point me in the direction of the correct rxjs operator to use and help troubleshooting the reason as to why those 2 solutions didn't work.

1 Answer 1

2

Walking through this code:

this.fetchRoles()
    .pipe(
        switchMap((roles: IUserSite[]) => this.getCurrentRoles(roles)),
        switchMap((role: string[]) => this.getLinkObjects(role)),
        tap((role) => this.linkObjects.push(role))
        // concat the objects emitted by switchMap
    )
    .subscribe();

It's assumed that this.fetchRoles() emits an array of UserSites.

The first switchMap will cancel any existing request and get the current roles for all of the UserSites in the array returned by this.fetchRoles(). This appears to emit a single array of strings. (I'm not clear on what these strings contain and how they relate to the linkObject name and link}

The second switchMap will cancel any existing request and get the link objects for the array of strings. This appears to return a role?

What is the type of role emitted from the second switchMap? (You can easily see this in your IDE if you hover over (role) in the tap operator.)

Can you confirm that this is what is intended? If this is not what was intended, can you modify your question to specify in words what the intended inputs and outputs of each operator should be?

Update: I'd recommend strongly typing your "role":

export interface Role {
   name: string,
   link: string[]
}

Then your getLinkObjects can be strongly typed:

public getLinkObjects(roles: string[]): Observable<Role>

Which should allow your tap to work as it is of the correct type to append to the array:

tap(role => this.linkObjects.push(role))
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for looking at this, I edited the question to answer your question. did my edits clarify ?
What is the type of role in the tap method? Is it of type any?
role: ILinksObject; interface ILinksObject { name: string; link: string[]; }
So it appears that they are already strongly typed everywhere? Are you seeing an error somewhere? Or is it just not appending it to the array?
OMG!! you caught the right place! theres a spelling mistake in that tap line, it worked when I added the type there! its this.linksObject not this.linkObject
|

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.