Skip to content

Controllers from Components attached to states not always activated in the same order #3168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cadilhac opened this issue Nov 22, 2016 · 3 comments
Milestone

Comments

@cadilhac
Copy link

cadilhac commented Nov 22, 2016

Using 1beta3

Because of a strange issue in my app, I realized something related to ui-router. I have a controller that broadcasts a message. This message is listened to in another controller. Sometimes, the message is caught, sometimes not. So I put some console.log in each $onInit of the controllers and they are anot always displayed in the same time. Obviously, in a particular order, the message is caught, in the other order, it isn't (since the listener did not register before the message was posted).

I understand that the context is vague but I will try to describe how the states are defined:

platform
|-- explore
| |-- userMarkerSelected

Here is the platform state:

        var platformState = {
            name: 'platform',
            redirectTo: 'explore',
            url: '/',
            views: {
                '': {
                    component: 'platform'
                },
                'main-map@platform': {
                    component: 'mainmap'   // This is the controller that listens to a message in $onInit
                }
            }
        }

Note that the main-map ui-view is no in a conditional node with ng-if or ng-show.
The userMarkerSelected state:

        var userMarkerSelectedState = {
            name: 'userMarkerSelected',
            parent: 'explore',
            url: '/user/:userid',
            views: {
                '': {
                    template: '<ui-view />'
                },
                'panel-content@platform': {
                    component: 'selecteduser'   // This is the controller that sends the message
                }
            }
        };

Since userMarkerSelected is a descendant state of platform, I expect that a view defined in the parent controller would be built before the view defined in a descendant. And as I told you sometimes yes (actually most of the time), but sometimes no.

So, if I console.log at the beginning of the controllers, this gives when it works:

Platform
Explore
MainMap
SelectedUser

and when this does not work:

Platform
Explore
SelectedUser
MainMap

Not sure what additional information I can give you.

Thanks

@christopherthielen
Copy link
Contributor

Although this behavior isn't explicitly defined, I agree that what you expect seems reasonable. I'm marking it as a bug.

The relevant logic is in the ViewService.sync code.

The code is sorting by ui-view depth so the top-most ui-views are updated first. However, it does not also sort by state from the uiViewConfigs.

This bug is low priority, so a PR would be appreciated.

@christopherthielen christopherthielen added this to the 1.0.0-rc.2 milestone Mar 14, 2017
@cadilhac
Copy link
Author

I checked your new code but I'm not very familiar with how this works. Could you please explain here how the sorting mechanism now works? Thanks.

@christopherthielen
Copy link
Contributor

christopherthielen commented Mar 21, 2017

@cadilhac

It sorts by <ui-view> nesting level as a primary sort. If two ui-views have the same nesting level, then it sorts by state nesting level.

<ui-view name="header"></ui-view>

<ui-view name="content">
  <!-- content from state 'foo' -->
  <ui-view name="nested">
    <!-- content from state 'foo.bar' -->
    BAR
  </ui-view>
</ui-view>

<ui-view name="footer"></ui-view>

This example, the header, footer, and content ui-views have view nesting level of 1.
The nested ui-view has a nesting level of 2.

If you fill the header with a component in state foo.bar.baz but fill footer with a component in state foo.bar, the footer is processed first. Both ui-view have the same view nesting level, but the component from foo.bar has a lower state nesting level than the component from foo.bar.baz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants