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

Can a component have it's own sub components + viewports? #117

Open
PascalPrecht opened this Issue Feb 19, 2015 · 37 comments

Comments

Projects
None yet
@PascalPrecht
Copy link
Contributor

PascalPrecht commented Feb 19, 2015

Giving the fact that each component is somehow isolated and independent, I wonder if it's possible to build a component that introduces sub components and viewports for itself, without coming from an outer routing.

Here's what I mean: We know that we can configure the router to map a route to more than one component like this:

app.controller('AppController', function ($router) {
  $router.config([
    {
      path: '/',
      components: {
        viewportA: 'navigation',
        viewportB: 'main'
      }
    }
  ]);
});

Now, when routing to / the components navigation and main are loaded into the viewports viewportA and viewportB.

Now imagine the following scenario:

We have our AppController that maps a route to a componentA like this:

app.controller('AppController', function ($router) {
  $router.config([
    {
      path: '/',
      component: 'componentA'
    }
  ]);
});

Now, the interesting part, componentA has a template like this:

<h1>Component A</h1>
<router-view-port="left"></router-view-port>
<router-view-port="right"></router-view-port>

And a router configuration like this:

app.controller('ComponentAController', function ($router) {
  $router.config([
    {
      path: ???
      components: {
        left: 'subComponentA',
        right: 'subComponentB'
      }
    }
  ]);
});

So componentA is a component, as we know, and it as it's own controller and introduces it's own viewports with it's own router. But as we can see in the code snippet, it's not very clear to what route that maps.

My question is, is that possible at all? That a component is so self-contained that it truly introduces it's own viewports and router? Or do I always have to define my custom "wrapper" route at application level that says "Hey I have this route here and we want to load two components in it.". But that also means, the start template (index.html) needs to have two viewports.

I hope my question is clear, if not please let me know!

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented Mar 6, 2015

I think "self-contained" components are essential to component driven Angular development, so yes, I believe it is an absolute must that components can contain their own viewports and have their own router.

If we think of routing as "mounting" components to "paths" where paths are concatenated to form a complete path, then a powerful pattern emerges.

This implies that each component starts from its own root path '/', which is the default path.

So to use your exact example:

app.controller('AppController', function ($router) {
  $router.config([
    {
      path: '/',
      component: 'componentA'
    }
  ]);
});

and:

<h1>Component A</h1>
<router-view-port="left"></router-view-port>
<router-view-port="right"></router-view-port>

with:

app.controller('ComponentAController', function ($router) {
  $router.config([
    {
      path: '/',
      components: {
        left: 'subComponentA',
        right: 'subComponentB'
      }
    }
  ]);
});

would concatenate / and / to form // and finally collapse to /.

Since each viewport creates a new child router, the paths don't conflict and the current router implementation should already support this.

All kinds of combinations are possible:

/ + / => /
/ + /sub => /sub
/main + / => /main/
/main + /sub => /main/sub

This is similar to how express works when mounting express apps using a prefix path.

So in short you can just use / as the path in your component if you don't want the component route to have its own url (you could consider it the default 'state' of the component when the parent component is is loaded).

Hope that makes sense?

@btford, @PascalPrecht — would be great to hear your thoughts on this.

@maximilianmikus

This comment has been minimized.

Copy link

maximilianmikus commented Mar 7, 2015

+1 express style route mounting for components

@csaloio

This comment has been minimized.

Copy link

csaloio commented Mar 8, 2015

@jvandemo I agree that would be ideal, however I don't think it currently works. Whenever I've tried to get a sub component to map a path such as /sub1 ng-link creates hrefs like /.undefined/sub1

It would be great if it worked as you describe but I don't think it does at least right now. I've yet to see any example of how child viewports/routing can be made to work so far.

@PascalPrecht

This comment has been minimized.

Copy link
Contributor

PascalPrecht commented Mar 18, 2015

@jvandemo Thank you so much for putting this together. At a first glance, this approach makes totes sense. I wonder if there are some edge cases where this idea won't fit though.

Am I getting that proposal right when thinking that this would also solve nested dependencies? Because in your proposal, you'd in fact assemble components via paths.

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented Mar 18, 2015

I agree that would be ideal, however I don't think it currently works. Whenever I've tried to get a sub component to map a path such as /sub1 ng-link creates hrefs like /.undefined/sub1

@csaloio1 — I have noticed that as well and I think it is a bug in the current implementation of the generate() method in the router.

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented Mar 18, 2015

@PascalPrecht — I think that makes sense as long as a component is activated first by its parent component.

So in the example above: even if there was a componentB with a ComponentBController that matches the same path (/) as componentA:

app.controller('ComponentBController', function ($router) {
  $router.config([
    {
      path: '/',
      components: {
        left: 'subComponentC',
        right: 'subComponentD'
      }
    }
  ]);
});

componentB would never be loaded, because it wasn't activated by the parent component:

app.controller('AppController', function ($router) {
  $router.config([
    {
      path: '/',
      component: 'componentA'
    }
  ]);
});

Does that make sense?

Thanks for sharing your thoughts!

@PascalPrecht

This comment has been minimized.

Copy link
Contributor

PascalPrecht commented Mar 18, 2015

@jvandemo Yes, get it!

@btford btford added the type: docs label Mar 28, 2015

@btford btford modified the milestone: Backlog Mar 28, 2015

@afitterling

This comment has been minimized.

Copy link

afitterling commented Apr 1, 2015

+1 (btw, has anyone setup a working example on github?)

@csaloio

This comment has been minimized.

Copy link

csaloio commented Apr 1, 2015

Does this being on the backlog milestone mean that this is not happening any time soon? Because if so, I can't see how one could ever use this router in anything beyond demoware.

@btford

This comment has been minimized.

Copy link
Contributor

btford commented Apr 1, 2015

@csaloio1 – this is already implemented. All that remains is to document it better to resolve @PascalPrecht's question.

@csaloio

This comment has been minimized.

Copy link

csaloio commented Apr 1, 2015

@btford That is great to hear. Looking forward to the documentation.

@upta

This comment has been minimized.

Copy link

upta commented Apr 14, 2015

@btford Just to clarify, does this only work if the child routes have some path beyond just '/'?

In my testing (granted, I'm very new to the new router ;), using the example from @PascalPrecht doing this threw an error:

app.controller('ComponentAController', function ($router) {
  $router.config([
    {
      path: "/",
      components: {
        left: 'subComponentA',
        right: 'subComponentB'
      }
    }
  ]);
});

but this worked (not allowing for a default setup for child components, since I'd have to route to /test):

app.controller('ComponentAController', function ($router) {
  $router.config([
    {
      path: "/test",
      components: {
        left: 'subComponentA',
        right: 'subComponentB'
      }
    }
  ]);
});
@shanonvl

This comment has been minimized.

Copy link

shanonvl commented Apr 21, 2015

@btford that's fantastic that it's implemented but I can't seem to get it to work... even using a very simple example. This is using angular 1.4.0.rc.0 (w aria + animate) and angular-new-router 0.5.3.

http://plnkr.co/edit/hNK8HNjLnGJdPw1APPDM?p=preview

If you can point in the right direction, I'd be happy to help work out some better examples for the documentation.

@csaloio

This comment has been minimized.

Copy link

csaloio commented Apr 21, 2015

@shanonvl Or do what I did and just switch to Aurelia :) http://aurelia.io/

@AlmeroSteyn

This comment has been minimized.

Copy link

AlmeroSteyn commented Apr 30, 2015

@shanonvl I am having the same issue.

Having parentComponent and childComponent I set up the following scenario:

Main app controller routing:

 $router.config(
            [
                {
                    path: '/parent',
                    component: 'parentComponent'
                }
            ]

This is then loaded into the main html with:

<ng-viewport></ng-viewport>

Then in the controller of parentComponent the following route is defined:

 $router.config(
            [
                {
                    path: '/',
                    component: 'childComponent'
                }
            ]

With the html in the view for parentComponent containing:

<ng-viewport="childComponent"></ng-viewport>

This simply does not work. When running it, I do see that the actual html element in the browser is:

<ng-viewport="childcomponent"></ng-viewport="childcomponent">

So it loses the camelcasing. Dunno if this is why it is losing the connection with the actual component to instantiate.

If I change the routing in the parentComponent to:

 $router.config(
            [
                {
                    path: '/child',
                    component: 'childComponent'
                }
            ]

And the html of the parentController to be the same as the viewport instance on the main page hosting the application:

<ng-viewport></ng-viewport>

Then I get to see both components on the page when I fist navigate to /parent and THEN add on /child manually.

Looking forward to getting this working :)

@PascalPrecht

This comment has been minimized.

Copy link
Contributor

PascalPrecht commented May 4, 2015

In fact I can't get it working either. Going to investigate now and see what I can do..

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 4, 2015

Here is a link to a codepen where sibling viewports are throwing an error: http://codepen.io/jvandemo/pen/WvQeYa?editors=101

error

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 4, 2015

I also created a plnkr for easier troubleshooting. It looks like the path property is missing from the instructions.

http://plnkr.co/edit/HBPUHhwnzhb9OO461MLI?p=info

plnkr

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 4, 2015

@PascalPrecht — I think a solution is in the making:

angular/angular@9d5c33f

@grbush

This comment has been minimized.

Copy link

grbush commented May 5, 2015

@jvandemo Great news, my team was wondering about the state of this project, but it looks like there's some very active development over at angular/angular. I wonder if those changes will be getting copied over to angular/router.

@PascalPrecht

This comment has been minimized.

Copy link
Contributor

PascalPrecht commented May 5, 2015

Yes. The router code is moved to angular/angular only temporarily in order
to take advantage of the build process. So at some point the latest and
greatest will be moved back to this repo
On May 5, 2015 1:20 PM, "Geoff Bush" notifications@github.com wrote:

@jvandemo https://github.com/jvandemo Great news, my team was wondering
about the state of this project, but it looks like there's some very active
development over at angular/angular. I wonder if those changes will be
getting copied over to angular/router.


Reply to this email directly or view it on GitHub
#117 (comment).

@SebastianSchirmer

This comment has been minimized.

Copy link

SebastianSchirmer commented May 5, 2015

@PascalPrecht any indication when that will happen? We are eagerly waiting for some bug fixes, otherwise we can't use the new router with 1.x. We are currently thinking of switching to ui-router ad interim and then to the new router as soon as fixes are backported to 1.x.

@PascalPrecht

This comment has been minimized.

Copy link
Contributor

PascalPrecht commented May 5, 2015

Using ui-router for now should be the right choice when it comes to super
complex scenarios
On May 5, 2015 1:43 PM, "Sebastian Schirmer" notifications@github.com
wrote:

@PascalPrecht https://github.com/PascalPrecht any indication when that
will happen? We are eagerly waiting for some bug fixes, otherwise we can't
use the new router with 1.x. We are currently thinking of switching to
ui-router ad interim and then to the new router as soon as fixes are
backported to 1.x.


Reply to this email directly or view it on GitHub
#117 (comment).

@SebastianSchirmer

This comment has been minimized.

Copy link

SebastianSchirmer commented May 5, 2015

@PascalPrecht Well, super-complex is probably not the proper wording, it's actually quite basic. See e.g. #193

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 5, 2015

@leschirmeur — There has been a lot of activity lately so I think @btford is really working hard to get Component Router ready for Angular 1.4 or Angular 1.5.

The general purpose of making Component Router available in Angular 1.x is to provide a router that allows you to write code that will be easy to port to Angular 2 (once it comes out).

If you need a stable router for your Angular 1.x application today and you don't care about Angular 2 yet, UI-router is probably your best choice.

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 5, 2015

@grbush@PascalPrecht is right. @btford has mentioned recently that all development is temporarily happening in the angular/angular repository.

Once the build process has been finalized, development will continue in the angular/router repository.

You can check out Brian's own words right here at the 3 minute mark in:
https://www.youtube.com/watch?v=sfV0ApyN5fM

@SebastianSchirmer

This comment has been minimized.

Copy link

SebastianSchirmer commented May 5, 2015

@jvandemo Thank you, we will switch to ui-router then

@grbush

This comment has been minimized.

Copy link

grbush commented May 5, 2015

@PascalPrecht @jvandemo Really appreciate the info thank you. We're super excited about the Component Router, architecting reusable components and basically just planning ahead so we can quickly move to angular2 when it's ready. For now I've cobbled together some 'fixes' (hacks?) that will allow us to prototype with what's in angular / router. Our project schedule allows us time to ship with angular 1.4 and component router 1.0 so eagerly awaiting updates :)

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 6, 2015

@leschirmeur — If your primary goal is to build a solid Angular 1.x application at the present without thinking about Angular 2 yet, I would make the same call.

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 6, 2015

@grbush — That's a luxury situation ;-) Would love to see your code when you have things running. Is it an open source project? Thanks!

@SebastianSchirmer

This comment has been minimized.

Copy link

SebastianSchirmer commented May 6, 2015

@jvandemo -- We have decided to go exactly this route, using the ui-router for the time being. Thanks for your input.

@AlmeroSteyn

This comment has been minimized.

Copy link

AlmeroSteyn commented May 6, 2015

@PascalPrecht @jvandemo Thanks for the info! Great to see the direction this is going in. Having the luxury to wait as well. Want to incorporate this is in some Angular training at the company I work for to focus a bit on the upgrade path to 2.0 for future projects.

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented May 6, 2015

@AlmeroSteyn — That is awesome. Would be great if you could share your experiences. From what we are able to see so far, I believe that Angular 2 and Component Router will be a very powerful combo in the future! Exciting stuff ahead!

@AlmeroSteyn

This comment has been minimized.

Copy link

AlmeroSteyn commented May 7, 2015

@jvandemo - I agree. One of the best parts, for me, is how it makes the upgrade to 2.0 less painful. So would want to push for it in new projects the minute it is in stable release.

Was translating ui-router functionality to new router functionality when I stumbled across this issue.

@guyjacks

This comment has been minimized.

Copy link

guyjacks commented Jun 28, 2015

Should child routes be working in 0.5.3 or have the changes in angular/angular not been ported over yet? I'm using angular 1.4

@wojciak

This comment has been minimized.

Copy link

wojciak commented Oct 22, 2015

Bumping this, is there a way to get child components running?

@jvandemo

This comment has been minimized.

Copy link
Contributor

jvandemo commented Oct 22, 2015

Here is a link to @btford's talk on the router a few days ago. That should hopefully clear up a lot of the confusion:

https://www.youtube.com/watch?v=z1NB-HG0ZH4

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