Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Multiple named ngView directives and attaching views to routes #1198

Closed
wants to merge 1 commit into from

Conversation

hkdobrev
Copy link
Contributor

Usage and purpose

Routes can have a view attached via the view property.
Views can be named like so:

    <div ng-view="subsection"></div>

Then you could create a route which will update only this view:

    $routeProvider.when('/somepath', {
        templateUrl: '/section-template.html',
        view: 'subsection'
    });

When the url is changed to '/somepath' only views named 'subsection' would
be updated. This should be used for:

  • subsections on the page which should respond to some routes,
    other views would not be changed
  • modal dialogs with their own url, like Pinterest, Trello etc.

Different Cases

  • a view has a name, but the route does not have a view set
    • the view is not updated
    • the route is considered to be a main route
    • the view is a secondary view.
  • the route has a view property, but a view is not named
    • the view is not named
    • the route is considered to be secondary
    • the view is (the) main view and would update only for main routes
  • the route has a view property and the view is named, but
    the name does not match
    • the view is not updated
    • the view is secondary
    • the route is secondary - it propably updates another view
  • the route has a view property and the view is named with the same
    • the view is updated regarding the template and the controller
      associated with the route
    • the route and view are secondary, but they are bound together

If the location is changed to a route which has a view attached, but
such view does not exist then AngularJS will do nothing and no view
will be updated.

Implementation

The whole thing is happening in the ngView directive on
$routeChangeSuccess event. When the update function in
ngView is called the view is updated only if the current route
and the view match.

$route.last is set to the previous route when a named view is updated.
This could be used from a developer to recover the location to
a previous path corresponding to a main route.

For example if you have a modal dialog with its own url and a matching route,
when the dialog is closed you would want to recover the url to the location
of the previous main route.

$route.interpolate() is exposed so it could be used in such scenario to
build the path using $route.last.params.

Usage and purpose
=================

Routes can have a view attached via the `view` property.
Views can be named like so:

	<div ng-view="subsection"></div>

Then you could create a route which will update only this view:

	$routeProvider.when('/somepath', {
		templateUrl: '/section-template.html',
		view: 'subsection'
	});

When the url is changed to '/somepath' only views named 'subsection' would
be updated. This should be used for:

 - subsections on the page which should respond to some routes,
  other views would not be changed

 - modal dialogs with their own url, like Pinterest, Trello etc.

Different Cases
===============

 - a view has a name, but the route does not have a view set

	 * the view is not updated
	 * the route is considered to be a main route
	 * the view is a secondary view.

 - the route has a `view` property, but a view is not named

 	 * the view is not named
 	 * the route is considered to be secondary
 	 * the view is (the) main view and would update only for main routes

 - the route has a `view` property and the view is named, but
 the name does not match

 	 * the view is not updated
 	 * the view is secondary
 	 * the route is secondary - it propably updates another view

 - the route has a `view` property and the view is named with the same

 	* the view is updated regarding the template and the controller
 	associated with the route
 	* the route and view are secondary, but they are bound together

If the location is changed to a route which has a view attached, but
such view does not exist then AngularJS will do nothing and no view
will be updated.

Implementation
==============

The whole thing is happening in the `ngView` directive on
`$routeChangeSuccess` event. When the `update` function in
`ngView` is called the view is updated only if the current route
and the view match.

`$route.last` is set to the previous route when a named view is updated.
This could be used from a developer to recover the location to
a previous path corresponding to a main route.

For example if you have a modal dialog with its own url and a matching route,
when the dialog is closed you would want to recover the url to the location
of the previous main route.

`$route.interpolate()` is exposed so it could be used in such scenario to
build the path using `$route.last.params`.
@kstep
Copy link
Contributor

kstep commented Jul 27, 2012

Why not user ng-include in your case?

@hkdobrev
Copy link
Contributor Author

Because I want to use the power of routes, route parameters and so on. In my specific case I have user profiles opening in a modal dialog. They have urls like: /users/123. If you open such url directly you should see the user profile in a dialog as well.

At first I tried to use ngInclude, but the problem is that I should remove the user route so the main content on the background does not disappear.

@mhevery
Copy link
Contributor

mhevery commented Sep 12, 2012

Thanks for your contribution! In order for us to be able to accept it, we ask you to sign our CLA (contributor's license agreement).

CLA is important for us to be able to avoid legal troubles down the road.

For individuals (a simple click-through form):
http://code.google.com/legal/individual-cla-v1.0.html

For corporations (print, sign and scan+email, fax or mail):
http://code.google.com/legal/corporate-cla-v1.0.html

@hkdobrev
Copy link
Contributor Author

Signed :)

@anotherpit
Copy link

Fails with currentRoute.$route is undefined when redirecting to default route:

.otherwise({
    redirectTo: '/something'
})

At least, in hashbang mode.

@hkdobrev
Copy link
Contributor Author

@anotherpit I have tried it in HTML5 mode with:

.otherwise({
    redirectTo: '/'
})

I'll look into that.

@anotherpit
Copy link

I slightly tweaked route.js to something like

    function update(event, next, last) {
        var current = $route.current,
            route = current && current.$route,
            locals = current && current.locals,
            template = locals && locals.$template;

        if ( !route && attr.ngView ) {
            return;
        }

        // …and so on
    }

Works fine for me. Sorry, can't pull it on GitHub right now.

@vishal1shukla2
Copy link

Is this part of any stable release of Angular? if no, is there any plan for it?

@hkdobrev
Copy link
Contributor Author

hkdobrev commented Nov 1, 2012

@vishal1shukla2 It is not part of a stable release or work from the AngularJS team. This is just a pull request which aims a review from the core team to be implemented in the core.

There were some discussions in the Google group about such feature and I've tried to implement it with the same interface as the core team wanted.

@alexwestholm
Copy link

Another +1 for merging this.

@anotherpit
Copy link

Not stable enough to merge. I posted a bug description earlier.

Moreover, the given solution doesn't let you configure several regions (ngViews) on the same route change, which is pretty expected when you deal with a complex layout (i.e. several named ngViews). It would be great to configure routes like this:

$routeProvider
    .when('/index', {
        // set up content region
        'content' : {
            templateUrl : 'indexPage.html'
        },
        // clear pop-up region
        'popup' : {
            template : ' '
        }
    })
    .when('/login', {
        // set up pop-up region
        'popup' : {
            templateUrl : 'loginPopup.html'
        }
        // doesn't change content region
    })
    .when('/logout', {
        // traditional redirect
        redirectTo : '/index'
    });

@anotherpit
Copy link

There were some discussions in the Google group about such feature and I've tried to implement it with the same interface as the core team wanted.

Link?

@orlenko
Copy link

orlenko commented Nov 12, 2012

@hkdobrev Thanks for the patch!

But to me it seems that the more common scenario involves a hierarchy of routes, not just arbitrary control over various parts of the document.

For example, an application has top-level sections with URLs: /dashboard and /news. The main outer structure of the page stays the same (header, logo, footer, sidebar), but the central ngView gets reloaded when we navigate from /news to /dashboard. So far, this works out of the box.

Under /dashboard, there's one or more child ngViews that get populated with longer URLs like /dashboard/articles?sort=latest or /dashboard/services?filter_topic=seo.

So, here's my ideal scenario when a URL like /dashboard/articles?sort=latest is clicked.

  • If /dashboard is already loaded, I want /dashboard/articles?sort=latest to load only the necessary client ngView.
  • If we're not inside /dashboard, I want /dashboard/articles?sort=latest to first load /dashboard view, wait for all its asynchronous initialization to complete (because some child views may load asynchronously), and then act as if /dashboard/articles?sort=latest was clicked from within the /dashboard view.

Before I learned about AngularJS, I had a custom implementation of this using jquery.address and a bunch of ugly custom code. But AngularJS has such elegance to it - do you think a hierarchical routes/views implementation with AngularJS is possible?

@anotherpit
Copy link

@orlenko Though such scenarios are pretty common, they also are pretty dynamic and usually heavily rely on exact application architecture and layout, so I suppose $routeChangeError/$routeUpdate event handlers to be proper way to implement it.

@orlenko
Copy link

orlenko commented Nov 13, 2012

Sigh... Okay :(

@rigolepe
Copy link

@anotherpit I'm also struggling with similar routing issues as those described by orlenko. If they are so common, why is it so hard to implement them? Or why is the solution with event handlers not described in one of the angular tutorials? I come from backbone and routing there is way more flexible than the current angular implementation.

I would like any controller to have acces to the $routeParams, even when they are not registered with the $routeProvider service. Unfortunately $routeParams is now an empty object for controllers that are not registered with the $routeProvider. I believe it's a fundamental flaw to tightly couple the routing functionality with template loading and a single controller. Especially when there is only a single ng-view directive allowed in the whole page.

+1 for merging hkdobrev's implementation (once stable)
+1 for a more flexible $routeProvider

@ramaralo
Copy link

This is an urgent issue! It makes a lot of sense. I have a similar need: https://groups.google.com/forum/#!topic/angular/ZhdpiuR8D_c

By the way:

$routeProvider.when('/somepath', {
templateUrl: '/section-template.html',
view: 'subsection',
controller: 'section-templateController'
});

In my opinion it makes no sense for angular to exist without this feature. Without it, apps will be monolithic and not optimized for the "closed for change open for extension" principle since every time we need new sections, we will have to edit the only view there is. If multiple views were possible, we could better control app upgrades.

Please consider this!
Thanks.

@mordendk
Copy link

Your opinion comes out pretty harsh ramaralo. While I see named views as a welcome addition, there are quite a few ways to accomplish similar functionality. The suggestions listed above or listening on $routeParams injected from an app-level config module would be a good place to start.

Good luck vanilla js'ing your "extensible multiple team plugin architecture" - of course there's a reason for Angular to exist. It's awesomeness squared and has really taken out a lot of the complexity I used to have in my projects - keep up the good work guys.

@jeme
Copy link

jeme commented Jan 15, 2013

@mordendk while it might be true that his opinion comes out harsh, but sometimes things just have to be said that way... I also find it strange that when "drill-down" is quite common, that this pattern isn't actually supported better than to reload the entire view and alternate on includes.

This gives the page a clunky feel, especially since the view reload (at least in my experience) is so noticeable.

Routing is so fundamental to me, so giving a much more flexible support for it makes sense to me. And besides, it seems that many of the other MVC frameworks is able to do just that, so why shouldn't Angular make it a priority to add features here?

@ramaralo
Copy link

@mordendk I agree with you. Sorry, it wasn't meant to be so harsh. And I did find a solution (at least I think I did, because the project is in stand by, now).

Thank you. ;)

@skrivanos
Copy link

@ramaralo could you please share your solution with us? Would be much appreciated.

@ramaralo
Copy link

@skrivanos Well, I haven't yet fully implemented it. Basically my approach relies on this ideas:

  • You can actually change only part of the view using includes. The example was there all along: http://docs.angularjs.org/api/ng.directive:ngInclude
    What we need to realize is that, the template you load into the view needs to have an include with its source being managed by your controller/model. And the template you include can be changed on run time. So this solved my problems of partial loading on each screen;
  • For several reasons, I can't have an angular module completely defined in one file. So, instead of having one module bootstraping automatically, I have one file defining my module:

myNameSpace.angularApp = angular.module('myModule', [], function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: 'templates/t1.html',
controller: function ($scope, $route, $routeParams, $location) {
// do something here
}
})
where t1,html can have as many includes as I want.
Then several other files are loaded for configuring new route behaviours:

myNameSpace.angularApp.config(function($routeProvider){
$routeProvider.when('/c', {
templateUrl: 'templates/t2.html',
controller: function ($scope, $route, $routeParams, $location) {
// do something here
}
});
});
Ok, this changes all of my page. But in my case this is good enough since the url also changes and each file that comes along configures a new screen. Keep in mind though, that all screens can still share the same model if you need to. Just use the $rootScope instead of $scope for your model.

And then, after all the files have been loaded, I bootstrap manually:

angular.bootstrap(document, ["myModule"]);

as in: http://docs.angularjs.org/guide/bootstrap

Let me know if this was of any help to you.

Best regards,
Ruben.

@hkdobrev
Copy link
Contributor Author

@ramaralo And when the URL changes you'd change/reload/re-render the whole
view? And you recommend using $rootScope just to share the same model with
this approach? IMHO you've just found a workaround for your problem. But
not an ideal solution.

As I said earlier, imagine a Trello-like or Pinterest-like app. The main
view is used for showing a big list of data items. Then you want every item
to be opened in a modal dialog or a sidebar. You'd certainly would not want
render the whole main view again. In addition named views could be used
both as nested views and not nested with the same level of functionality.

@ramaralo
Copy link

@hkdobrev Yes. Any solution will always be a workaround. Most certainly I'm not seeing the all picture, but if you want to open, let's call it an item, on a modal dialog of your "Pintrest" app, without a view reload, couldn't that be achieved by a specific directive? Imagine a directive called popup, for example activated by a variable on your model like popupOpen = true | false. What I mean is that if the feature you need doesn't need to change all the view, I think it should be implemented as a directive.

What do you think?

@jeme
Copy link

jeme commented Jan 16, 2013

@ramaralo for me personally this isn't to solve a dialog use-case for me (2), but rather the sub-section case (1), yes it can properly be implemented as a new directive. But since we wan't URL's to reflect where we are as in:

/ -> display a dashboard with some new changes and available resources (no category list for items as we are not yet in that focus)
/item -> open a list of newest items, display all categories at right (do not reload categories)
/item/category/somecat-> open a list of items from a specific category, display all categories at right (do not reload categories)
/item/123 -> open a specific item, display all categories at right (do not reload categories)
/item/123/edit -> open a specific item, open it's edit dialog.

I think it will either cause for confusion or just be straight up strange if we don't add some support for it in the routing, so that we can express what we wan't.

Especially because even changing from e.g. /item/123 to /item/432 would call for a full reload of the NG view, which then would include the "category" lists etc. And that is completely unneeded.

Right now I have my own solution, solved with a sub-route pattern as such:

 $routeProvider
        .when('/article',
        {
            templateUrl: '/tpl/views/article/root.html',
            controller: dotjem.ArticleController,
            subroutes: { 
                '/category/:category': { customdata: { sw: 0 } },
                '/archive/:month': { customdata: { sw: 0 } },
                '/:id': { customdata: { sw: 1 } }
                }
        });

As I found that more "expressive" towards what I wanted.

And then I have left it to the controller to react on "subroutes" for maximum flexibility on what happens on those... Not a solution I am happy with atm. because I also manually need to react to the specific subroute on a full reload (e.g. when we are on /blog/category/myCategory and hits F5) Also that custom data annoys me at the moment.

In any case, this still means I have had to add changes to "route.js"...

(and from here on out I use ngInclude to dynamically change the template of the core content, but keep the category lists etc. intact)

@ramaralo
Copy link

@jeme I can understand you point. This is were not having named views will have different impacts on different projects. On my case I think I would rather have a full view refresh since either way I would not be satisfied with the solution. But you got me confused with that subroutes attribute. It is not mentioned on the angular docs (http://docs.angularjs.org/api/ng.$routeProvider)... Can attributes be added to the second argument of the "when" method? If so, will they be available on the conttroler?

@veroniquepelletier
Copy link

+1 to merge

@jeme
Copy link

jeme commented Jan 16, 2013

@ramaralo The sub route pattern as you see it in my example did require changes to the original routing as I mentioned, so I have a fork...

But as for your question regarding if we can add our own "objects" to the route, then the answer is yes, you can do that and then obtain them in the controller through depending on $route, and then go through $route.current.$route and that will be that whole object you define as the second parameter to when. (except for routes defining a redirect to I think)

If you listen to the route change and route update events, whose will also be that object.
since they are called as this:

  • $rootScope.$broadcast('$routeUpdate', last);
  • $rootScope.$broadcast('$routeChangeStart', next, last);
  • $rootScope.$broadcast('$routeChangeSuccess', next, last);
  • $rootScope.$broadcast('$routeChangeError', next, last, error);

You should be able to catch those on a scope and react as well...
Note however that your controller will be created after all those have fired with the standard ngView implementation (afaik)... Existing controllers will ofc. be able to pick em up, as well as directives...

So that way, the feature as proposed here could properly be added purely thought custom view directives who listen on that event, looks if they are the target, and if so then respond to the event... That leaves the initial loading though, these views would need a "initial state".

@leeola
Copy link

leeola commented Jan 17, 2013

👍

A very awesome feature that is missing.

@mhevery
Copy link
Contributor

mhevery commented Jan 18, 2013

Thanks for all this hard work, but I don't think this solution fits our vision. The multiple view problem is complex since we want to preserve deep linking. Which means that each view needs to be controlled by a portion of the URL. In your current implementation as the URLs change different views get updated, but then refreshing the page couses all but the current view to be destroyed. This prevents deep linking, and it means that the URL does not contain all of the view state.

My gut feeling is that this will require a complete rethinking of the $route service to support this use case.

I am sorry I can not provide a more detailed analysis of what a solution would look like, I only know that the current proposed solution breaks certain things. We do want multiple view feature, but unfortunately we don't think this approach would work.

I am going to close this for now. If you can address these issues feel free to reopen.

@mhevery mhevery closed this Jan 18, 2013
@ProLoser
Copy link
Contributor

In the mean time... checkout my fairly kickass and highly versatile solution:

http://plnkr.co/edit/vWFliiEH1lJRItoxoeMk?p=preview and hit the blue fullscreen button in the top-right corner.

@jeme
Copy link

jeme commented Jan 18, 2013

@ProLoser I think that"poor workaround" is well known, but ones you put to much into the top level view (ng-repeats etc) it becomes increasingly visible that that portion is also reloaded, that's what is undesirable. (and for some it will properly also generate extra server requests)

@mhevery thanks for the update, I agree that this requires some rethinking, is there somewhere were we could have that dialog where the angular team would be ensured to participate with input and their own ideas, would the mailing list be that place? Especially people with a deep connection into routing and how it works.

@hkdobrev
Copy link
Contributor Author

@mhevery Though I agree my PR is far from ideal, I want to clarify that it supports deep linking.

For example if you have the following routes:

/sections (with no view attached a.k.a main content)
/sections/:section (with a "sub-view" attached)

Then if you link to a /sections/:section URL you will get the sub view. When you close it in some way (back button, closing modal or other navigation) and go to /sections, your main view will load then.

Though I have some more changes to the AngularJS code beside that on the website I have developped with the framework, you can check that out:

http://flingflung.com

The website shows a feed of users as main content and it opens user profiles in a popup. When you open/close a user profile the main view is not reloaded. The $viewContentLoaded event is fired, but with an additional isNew argument which indicates whether it needs to reload the content.

Probably I will add this functionality to the pull request when I have the time.

@lrlopez
Copy link
Contributor

lrlopez commented Jan 18, 2013

@mhevery, if you are rethinking the $route service to include nested views I'd recommend having a look into this:
http://www.bennadel.com/blog/2441-Nested-Views-Routing-And-Deep-Linking-With-AngularJS.htm

It's flexible enough although easy to understand and to implement. May be it could be useful have some built-in support from AngularJS...

@ProLoser
Copy link
Contributor

@lrlopez that is now the fourth version of nested routing I've seen.

I've done some poking around and testing and realized the shortcomings of my approach and the main advantage to some of these nested routing systems.

I have a proposal for anyone interested:

There have been many approaches to nested routes and the core team is still trying to figure it out.

Would anyone like to join the AngularUI org and form a team specifically for focusing a solution for nested routing?

There is a lot of discrepency and inconsistency across all the solutions and it's not quite clear which one is the easiest or best to use, so it would be nice if I could get by a solution I stand behind, especially if it merges everyone's efforts.

@ProLoser
Copy link
Contributor

For those that care: https://github.com/angular-ui/ui-router/

We started a new project over at AngularUI to develop a communally accepted best solution for Nested Routes. Everyone is free to join the discussion and we want more team members!

If we can refine a good solution then it may help the core team by giving them a stable solution that might be mergable in the future.

@sym3tri
Copy link

sym3tri commented Feb 26, 2013

+1 for some kind of solution to this basic problem.

@coli
Copy link

coli commented Mar 11, 2013

EmberJS has a very interesting nested route design http://www.thesoftwaresimpleton.com/blog/2012/08/20/routing_update/

@ProLoser
Copy link
Contributor

@coli you may want to refer to the link I posted earlier as it follows very closely the EmberJS strategy and tries to collect the best of all solutions.

@coli
Copy link

coli commented Mar 11, 2013

@ProLoser You mean ui-router? I just started looking at it and so far I'm very impressed. We have a difficult requirement of 3rd party extension into our UI, and the named view concept + inherited(?) stateParams is looking very good right now.

It also look like nested resolve() function is a good solution to flickering as well. (won't cover every case, but most cases)

@rynz
Copy link

rynz commented Apr 11, 2013

@ProLoser @mhevery Angular UI's ui-router project is looking very promising. Could we expect something like this being implemented in Angular JS Core at some stage?

@lrlopez
Copy link
Contributor

lrlopez commented Apr 11, 2013

If I'm not wrong, the idea behind ui-router is to replace the actual ng-view system in the future or, at least, to be distributed as an additional module (like ng-resource). There was some interaction with the core team at the design stage along these lines.

@coli
Copy link

coli commented Apr 11, 2013

I think a better approach is to remove ng-view/router from the default angular distro. And just let people pick their own router implementation.

Ui-router is fantastic, but it's a lot more complicated than expected for basic scenarios.

@sym3tri
Copy link

sym3tri commented Apr 11, 2013

IMO I think a routing system is essential for any complex web app, and if Angular intends to be a solution for building complex web apps it should include this core feature.

I like Ui-router, but I do agree that it's probably overkill for general use.

@ProLoser
Copy link
Contributor

If you guys can provide feedback on ui-router on ways we can simplify things it'd be greatly appreciated. We are quite open to input from the community as that's how the project was started. It is currently back-compat with the existing router.

@lrlopez
Copy link
Contributor

lrlopez commented Apr 11, 2013

I may be biased, but I don't think ui-router is too complex for simple scenarios.

You could just use this way: (taken from the wiki)

$stateProvider
    .state('contacts', {
        url: "/contacts",
        templateUrl: 'contacts.html'
    })

That would replace ui-view with the template when the URL matches.

From there you could progressively enhance the functionality using parameters, controllers, nested states, etc.

Also, as @ProLoser said, their is an optional back-compatibility module that could allow using the new system with existing projects.

@coli
Copy link

coli commented Apr 11, 2013

Is there a mailing list for ui-router?
But some things I hit last week touching ui-router for the first time. Maybe it's not so basic :)

  1. I has a abstract state, and a child state off that. I thought I could use a single ui-view. But turns out I need 1 ui-view for the abstract state, and 1 nested ui-view for the child state. It was not obvious this be the case.
  2. It was not obvious that nested state's url inherit/append off parent url. (Quite hard to debug)
  3. ui-router code was very hard to follow compared to angular.js code in general.
  4. I had a <a href="#" onclick="state.transitionTo(''dfgdf"), took a really long time to figure out why a redirect to / is happening! I thought it was some child/url routing quirk, it was the href...
  5. Lack of a Angular API doc like API doc :) Eg: $urlRouterProvider usage

@lrlopez
Copy link
Contributor

lrlopez commented Apr 11, 2013

Sorry Eddie, it seems I didn't explain my point well enough. You're completely right, ui-router can be complex, very complex, but those complexities come from using the advanced features like nested/abstract states or multiple & simultaneous views.

I was talking about simple scenarios, similar to the ones covered by the Angular original routing system. My bad :)

I agree with you. There is a lot of work ahead, especially on documentation. Most of your problems could have been solved by a good tutorial:

  1. You can use named views so you don't have to nested ui-views.
  2. Yes, it should be clearly stated on the docs.
  3. Take into account that is much more complex, so it's reasonable.
  4. Another tip to be included on the docs :)
  5. This should work, but I don't know if it covers everything you need: http://angular-ui.github.io/ui-router/build/doc/

About the mailing-list, there is one: https://groups.google.com/forum/#!categories/angular-ui/router . It hasn't much activity yet, though. May be you could get a faster response opening an issue at the repository: https://github.com/angular-ui/ui-router/issues

I really like the work that those guys have done so far. Please, don't hesitate in giving them feedback, it can only make ui-router better for everyone.

@rynz
Copy link

rynz commented Apr 11, 2013

@ProLoser @lrlopez I also agree it' couldn't be simplified any more than it is. I think the complexity people feel it has may be due to the example incorporating backwards compatibility. Perhaps it may worth incorporating an example without backwards compatibility and a comparison to Angular's default implementation.

Angular JS Route

angular.module('app', []).
  // App configuration.
  config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/', {
        template: '<div>Home Page</div>',
        controller: 'HomeCtrl'
      })
      .when('/contacts', {
        templateUrl: 'contacts.html',
        controller: 'ContactCtrl'
      });
  }]);

UI Router

angular.module('app', ['ui.compat']).
  // App configuration.
  config(['$stateProvider', function($stateProvider) {
    $stateProvider
      .state('home', {
        url: '/',
        template: '<div>Home Page</div>',
        controller: 'HomeCtrl'
      })
      .state('contacts', {
        url: '/contacts',
        templateUrl: 'contacts.html',
        controller: 'ContactCtrl'
      });
  }]);

The only real difference being that we name the state and provide the url in the params object.

Maybe it would also be worth taking the example from http://docs.angularjs.org/tutorial/step_07 and doing an comparison of the $routeProvider using $stateProvider instead.

As well as explaining that if people want to use otherwise() method it is handled by the $urlRouterProvider and the reasoning why a separate provider is used rather than chaining it from $stateProvider

$urlRouterProvider
      .otherwise('/');

@fluxsaas
Copy link

+1 for a solution implemented in the core.

i'm a angularjs "tester" (rails/backbone user, but i started to evaluate other frameworks) i would not use angularjs if i had to start with doing workarounds for that basic problem.

i have to solve exactly that problem: http://angular-ui.github.io/ui-router/sample/#/contacts/42.
additional to that, i have organized the user in folders (folder has_many users) which would mean an extra request to reload/render the folders with users.

other than that, angularjs feels pretty awesome!

@lessless
Copy link

how it's going?

@stakach
Copy link

stakach commented Jul 30, 2013

I've created https://github.com/cotag/ngRouteNames that provides much of this functionality whilst reducing the complexity.

State is represented in the URL, links are able to change a subset of the state or url and sub-views can be defined by ng-switch on $routeParams

Done with minimal overhead and uses the existing routing system with a bit of extended functionality

@hkdobrev hkdobrev deleted the multple-ngViews branch March 22, 2017 21:29
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.