Skip to content
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

Router - Proposal for creating bindings #5875

Closed
gionkunz opened this issue Dec 14, 2015 · 9 comments
Closed

Router - Proposal for creating bindings #5875

gionkunz opened this issue Dec 14, 2015 · 9 comments

Comments

@gionkunz
Copy link
Contributor

@gionkunz gionkunz commented Dec 14, 2015

The router is great but also comes with a very imperative way of handling things. It's sometimes very hard to leverage the full potential of a component based UI approach when using a router. With my current understanding of the Angular2 router I came to the conclusion that the current design has the following implications:

  1. If a component is created dynamically by the router, it automatically looses any connections to the parent component as the template is the glue to the parent component, which is missing when using the Router.
  2. Already existing input and output properties no longer work and the whole component needs to be redesigned to work with the router.
  3. Each component used in routing will break any existing event chain as the component will not be able to bind to a function of a component higher up. The component is not able to propagate in the UI component tree.
  4. Components that are used in pure UI composition differ from components used in routes quite a lot because of the above implications. I consider this a problem as one needs to decide if the component will be build for pure UI composition or for composition by the router. Components build for routing don't use input properties and events but rather rely on the router lifecycle hooks. They are also responsible to load any required data based on the route parameters on their own. From a user interface component standpoint this will break their re-usablity.

I wanted to open this issue as a discussion starting point because maybe other people feel the same. I also came up with a very naive example of how this problem could be solved. It uses a directive that will configure routes from the template and uses templates to activate components that can now be configured declaratively within the view. Additionally the syntax in the binding of the directive allows to extract the resulting ComponentInstruction on activation.
See second comment for updated proposal

What do you think? @btford @mhevery

Cheers
Gion

@gionkunz
Copy link
Contributor Author

@gionkunz gionkunz commented Dec 17, 2015

An alternative solution would be to provide an optional host template on the route configuration objects.

@Component({
  selector: 'child'
  template: `
    <h2>Child</h2>
    <p>Param: {{param}}</p>
    <button (click)="event.next(this)">Event</button>
  `
})
export class Child {
  @Input param;
  @Output event = new EventEmitter();
}

@Component({
  selector: 'app'
  template: `
    <h1>App</h1>
    <a *ngFor="#child of children" [routerLink]="['/Child/' + child.id]">Child {{child.id}}</a>

    <router-outlet></router-outlet>
  `,
  directives: [Child, RouterOutlet, RouterLink, NgFor]
})
@RouteConfig([
   {path: '/child/:id', name: 'Child', component: Child, hostTemplate: `
      <child [param]="getChild(routeInstruction.params.get('id'))"
             (event)="onEvent($event)">
      </child>
   `}
])
export class App {
  children: [
    {id: 1, param: 'Param 1'},
    {id: 2, param: 'Param 2'},
    {id: 3, param: 'Param 3'}
  ]

  getChild(id) {
    return this.children.find((child) => child.id === id);
  }

  onEvent() {

  }
}
@yfain
Copy link

@yfain yfain commented Jan 3, 2016

When I learned about Input and output parameters I was happy as it allowed creating losely-coupled components. Then I started to see if it would be possible to use a component with input/output params with the router. Unfortunately it's not possible. This basically means that input/output params work only if used within the same route, which is not nice. In other words, a component with input/ output parameters has limited reusability.

I also vote for an addition of something that would allow to configure component's input/output params in the @RouteConfig annotation.

@Namek
Copy link

@Namek Namek commented Feb 3, 2016

Lack of @Input support in routing is not nice (RouteParams for a workaround...) but lack of support for @Output (???) it's a huge mistake. Whole framework looks like something randomly crafted and not really designed, thanks to things like those.

Components that are used in pure UI composition differ from components used in routes quite a lot because of the above implications. I consider this a problem as one needs to decide if the component will be build for pure UI composition or for composition by the router.

Totally agree. There shouldn't be much difference, maybe except RouteParams.

I believe that current Router tries too much rule the component world. It creates components, destroys them and navigate. I believe that Router should only navigate.

I also vote for an addition of something that would allow to configure component's input/output params in the @RouteConfig annotation.

Sounds like fixing what we got but I'm sure that's a minimum.

@btford I've read that you're responsible for Router, could you refer to this topic somehow? Are there any plans about @Input and @Output in respect of Router?

@Namek
Copy link

@Namek Namek commented Feb 3, 2016

To access child component created by router and subscribe to child's events I use this for now:

@ViewChild(AllProducts) allProducts;

ngAfterViewInit() {
    this.subscribeToEvents()
    this.router.parent.subscribe(() => this.subscribeToEvents())
}

private subscribeToEvents() {
    if (!!this.allProducts) {
        this.allProducts.productRowDoubleClicked.subscribe((pid) => {
            this.openProductTab(pid)
        })
    }
}

where productRowDoubleClicked is @Output productRowDoubleClicked = new EventEmitter() in AllProducts component

@gionkunz gionkunz changed the title Router - Proposal for configuration within template using RouterTemplateConfig directive Router - Proposal for creating bindings Feb 24, 2016
@vicb
Copy link
Contributor

@vicb vicb commented Sep 24, 2016

obsolete releates to the former router

@vicb vicb closed this Sep 24, 2016
@langdonx
Copy link

@langdonx langdonx commented Mar 22, 2017

I just came to the same conclusion as @gionkunz and was wondering if this was a solved problem? I'm looking for a solution for AngularJS specifically as I'm not on Angular. If it has been solved with Angular though, I'd be interested in how it works (if there's a link with information).

As best I can tell with the new 1.0 ui-router, they're still pushing $broadcast for component communication.

An example of what I'm looking to do, but with routing
^- employee-list component displays employee-editor component, which triggers onChange informing employee-list to refresh.

TIA!

CC @christopherthielen

@christopherthielen
Copy link

@christopherthielen christopherthielen commented Mar 22, 2017

@langdonx
Copy link

@langdonx langdonx commented Mar 22, 2017

@christopherthielen Thanks so much for the prompt reply! I apparently failed to see the "Routed parent/child component communication" section when I last perused. Events on ui-view is exactly what I needed.

@angular-automatic-lock-bot
Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Sep 11, 2019

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.