Skip to content

Make resolves/guards injectable/gettable in other resolves/guards on the same level #15032

Closed

Description

@dietergeerts

I'm submitting a ... (check one with "x")

[ ] bug report => search github for a similar issue or PR before submitting
[x] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

In a resolve, we are able to get the data from resolves on the parents, but not from the same level, so we need to do:

[
        {
            canActivate: [PlannerForGuard],
            canActivateChild: [PlannerForGuard],
            children: [
                {
                    canActivateChild: [PlannerForGuard],
                    children: [
                        {
                            canActivate: [RedirectToLastRunGuard],
                            canActivateChild: [PlannerForGuard],
                            children: [
                                {
                                    component: RunsComponent,
                                    path: 'runs/:runId',
                                    resolve: {
                                        deleteRun: DeleteRunResolve,
                                        run: RunResolve
                                    }
                                },
                                {
                                    canActivate: [RedirectToLastRunGuard],
                                    component: RunsComponent,
                                    path: 'runs'
                                }
                            ],
                            component: SimulationComponent,
                            path: '',
                            resolve: {
                                createRun: CreateRunResolve,
                                createSimulation: CreateSimulationResolve,
                                deleteSimulation: DeleteSimulationResolve
                            }
                        }
                    ],
                    path: '',
                    resolve: {
                        runs: RunsResolve
                    }
                }
            ],
            path: '',
            resolve: {
                simulation: SimulationResolve
            }
        }
    ]

Expected behavior

This could be so much simplified if resolves/guards can 'wait' for other resolves/guards on the same level, like this (it will also make for less guard checks....):

[
    {
        canActivate: [PlannerForGuard, RedirectToLastRunGuard],
        canActivateChild: [PlannerForGuard],
        children: [
            {
                component: RunsComponent,
                path: 'runs/:runId',
                resolve: {
                    deleteRun: DeleteRunResolve,
                    run: RunResolve
                }
            },
            {
                canActivate: [RedirectToLastRunGuard],
                component: RunsComponent,
                path: 'runs'
            }
        ],
        component: SimulationComponent,
        path: '',
        resolve: {
            createRun: CreateRunResolve,
            createSimulation: CreateSimulationResolve,
            deleteSimulation: DeleteSimulationResolve,
            runs: RunsResolve,
            simulation: SimulationResolve
        }
    }
]

What is the motivation / use case for changing the behavior?

It would allow for less, clearer code + less runs of guards + speed up resolving resolves (as it's now done per level) + no more .parent.parent..... to get the parent resolves (or a custom function to search for a resolve by name ;))

Activity

  1. dietergeerts commented on Mar 9, 2017

    @dietergeerts
    Author

    Ow, I just found out that we can't get resolve data in guards, even from the parents... thats REALLY BAD!

  2. DzmitryShylovich commented on Mar 13, 2017

    @DzmitryShylovich
    Contributor

    @dietergeerts I'm not fully understand your problem. Please add a small plunkr

  3. dietergeerts commented on Mar 20, 2017

    @dietergeerts
    Author

    @DzmitryShylovich, what it comes to is the following:

    ...
    resolve: {
        a: AResolve,
        b: BResolve
    }
    ...
    

    BResolve needs a to process, so inside the resolve function of BResolve, I want to wait for the resolve of AResolve, but right now, we can only get the resolved data from parents. If I'm overlooking the obvious, and BResolve can get the resolved value a, then please tell me how.

  4. DzmitryShylovich commented on Mar 30, 2017

    @DzmitryShylovich
    Contributor

    BResolve needs a to process, so inside the resolve function of BResolve, I want to wait for the resolve of AResolve, but right now, we can only get the resolved data from parents.

    so you want to access data from AResolve inside BResolve, correct? if yes, why wouldn't you combine them into a single resolver? It would simplify things.

  5. DzmitryShylovich commented on Mar 30, 2017

    @DzmitryShylovich
    Contributor

    there's another issue #14279 where people want to run resolvers concurrently so we need to make this configurable

  6. dietergeerts commented on Mar 31, 2017

    @dietergeerts
    Author

    @DzmitryShylovich , nope, it need to be two resolves, as on other routes, I have them in different levels + they resolve to two separate observables. Putting them together will just end up in code duplication, which is very bad, as you have to make sure you edit it in all places....
    I use resolves to construct the app state, where some states depend on others, but the level they are on isn't always known.

  7. kenisteward commented on May 26, 2017

    @kenisteward

    @dietergeerts I'm at the same brick wall. I actually went as far as to step through all the code for resolvers to make sure i wasn't crazy. What's even more confusing is I figured if I simply made a

    this.router.events.subscribe() in the resolver and had it wait for other ones to be done or even looped until it resolved the correct none undefined data that it would work. Sadly that doesn't even work!

  8. dietergeerts commented on May 29, 2017

    @dietergeerts
    Author

    @kenisteward , the only way to have them wait for each other is to have component-less, path-less route levels where you can define each level of dependent resolves. BUT it leads to several other issues, like secondary routes that don't work because of the path-less parent, performance impact, as each level is being resolved in series, routerLinks you have to edit each time, as '../' goes up one router config level, and not actually the url, like you would expect.

    Imho, the router, though rewritten several times, still isn't designed well for bigger applications... It's even hard to find good examples on how to use resolves in the official docs. It's like they just put it there because ui-router has them... Resolves should be preferred over injecting services into components.

  9. kenisteward commented on May 29, 2017

    @kenisteward

    @dietergeerts I think it can simply be resolved by adding an order to same level resolves. The router has the context of every resolver in the same level so if it just checks for an order it can allow resolvers on the same level to get each data.

    The real issue is for some reason it was made to not add the resolve data until all resolvers finish which makes sense in context just doesn't hit our use case

  10. dietergeerts commented on May 31, 2017

    @dietergeerts
    Author

    They should made the all available in the resolves, so you can subscribe to others, even if they are on the same level or not. It should not matter, as it can be that you move one later on, and then you don't want to rewrite resolves that depend on that one.

  11. kenisteward commented on Jun 5, 2017

    @kenisteward

    @dietergeerts the only reason I disagree with that is the whole mantra of Angular is Unidirectional data. if an earlier resolve could change based off a later resolve that would spell bad news bears for that mantra.

    Now as for the same level it would make sense for you to at the very least say make this one run last or something.

  12. dietergeerts commented on Jun 5, 2017

    @dietergeerts
    Author

    @kenisteward , well, it's not the actual resolve that will change. I return observables (rxjs) with those resolves, and the result of these observables is part of the application state. But when something happens, for example, the detail view is updated, then the list have to be updated too, so an event is thrown, the list observable picks it up, and the view is updated, no resolves are changing, just the data of the observables that were given by the resolves. I hope this makes sense.

    So basically, resolves are there, for me, to build up the application state tree.

  13. Toub commented on Sep 1, 2017

    @Toub

    Here is an API suggestion to address theses issue: #18247 (comment)

  14. added this to the Backlog milestone on Jan 23, 2018
  15. trotyl commented on Jun 9, 2018

    @trotyl
    Contributor

    Related to #10838

  16. angular-robot commented on Jun 5, 2021

    @angular-robot
    Contributor

    Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

    Find more details about Angular's feature request process in our documentation.

  17. angular-robot commented on Jun 25, 2021

    @angular-robot
    Contributor

    Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

    We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

    You can find more details about the feature request process in our documentation.

  18. atscott commented on Jul 23, 2021

    @atscott
    Contributor

    Duplicate of #40577 which is now tracked in #42953

  19. angular-automatic-lock-bot commented on Aug 23, 2021

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  20. locked and limited conversation to collaborators on Aug 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: routerfeatureLabel used to distinguish feature request from other issues

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions