I've tried my luck at the Gitter channels with limited success so I'm trying my last resort :)
What's the current way of importing the new component router to a project?
I see most recent work is in angular/angular repo but don't seem to find a recent package anywhere.
The JSPM angular-new-router
package points to @btford's repo and brings version 0.5.3 which looks pretty outdated.
+1
@georgiosd Since the new router isn't published yet, you're gonna have to build it from source using the http://github.com/angular/angular repo. From there you can take the built file (angular_1_router.js) and use it
Here is a plunkr with the latest build as of today.
That's wonderful, thank you. Is there an ETA on a release currently?
I have no idea. I thought the new router was supposed to come with 1.5, but we'll have to wait and see.
Indeed! Thanks, closing this now!
@brandonroberts what sequence of commands do you use to build the router?
I did the "normal" npm install
npm build.js
steps and didn't get an angular_1_router.js
file...
@georgiosd you need to run gulp buildRouter.dev
. It will put the angular_1_router.js in your dist folder.
@brandonroberts can you give us all the sequence of commands to build the router ? I'm a newbie on gulp and it doesn't work with me.
@vguede Sure. You need to have at least node 5 and at least npm 3.x installed.
Install gulp globally npm install -g gulp@latest
Clone the angular 2 repo: git clone [email protected]:angular/angular.git angular2
Go into the angular2 directory and install the dependencies cd angular2
and npm install
After npm finishes, run the gulp command to build the router file gulp buildRouter.dev
The angular_1_router.js
file will be in your angular2/dist folder.
Hope this helps
@brandonroberts It works fine ! Many thanks !
@brandonroberts Thanks for the info. I couldn't use child routes correctly, and can't find any example with child routes. I expanded the plunker you sent with a child route, as I understand it should be used.
http://plnkr.co/edit/5PyC9MjSaI5xC3fZRkgw?p=preview
The Home component has a new outlet, and configures a new route at "/", but this fails with
Error: Configuration '/' conflicts with existing route '/'
I don't think it should conflict, since the home controller is configuring a child route, it look's like the home controller is receiving the top router instead of a child one.
I based this on this presentation: https://docs.google.com/presentation/d/1bGyuMqYWYXPScnldAZuxqgnCdtgvXE54HhKds8IIPyI/edit#slide=id.gcbc539c5a_2_619
Can someone help me understand how to set up child routes, or point me to a working sample?
@pauloya Setting up child routes in Angular 1 is a little different then setting them up in Angular 2. To setup up your child routes, you have to place a $routeConfig property on your directive factory function in the parent directive. I forked your plunk and updated it with a working example.
http://plnkr.co/edit/2ZNQzWfspvpmMCLRBOdN?p=preview
If you also want to look at another example, Its using the upcoming component helper, but the concepts are the same. https://github.com/brandonroberts/angularjs-component-router
If you want a newer build you can install the router from npm now.
npm install @angular/router
Many thanks @brandonroberts for npm !
That's exactly what I needed, thanks!
@brandonroberts You have the same bug templateUrl <=> $onActivate (issue : angular/angular#4633) on angularjs-component-router.
Have you any idea when this bug will be fixed ?
@vguede I have no idea when it will be fixed. I normally have a build step that imports the html as is and use the template property.
Thanks @brandonroberts, I got things working using module.component() !
I'm not sure how I'm supposed to inject and use $router in the component.
I want to call navigate() programmatically, and also read the params.
http://plnkr.co/edit/xdEYFmUCv0xzvEbXrh0p?p=preview
In this plunkr I added a call to navigate, but it doesn't work unless I use _childrouter:
$router._childRouter.navigate([...])
Thanks!
@pauloya I thought whenever you inject the router it will use that component as the parent component for navigating and creating links. In the case of your example, you need to change
$router.navigate(['./Son']);
to
$router.navigate[('/Home', 'Son']);
If you want to use parameters with a route, just add the params after each component in the array
$router.navigate(['/Home', {name:'HomeParam'}, 'Son', {name:'SonParam'}]);
Thanks @brandonroberts.
But the ng-link
in the template uses the relative link ['./Son']
.
I thought I would be able to the same on the controller.
@pauloya I thought so also. It may be a bug, but I'm not sure.
It's a nice discussion and helps to find some answers for router
@pauloya the router delegates navigation to the root router, which explains why you have to provide the full route path even in a child component when navigating programmatically.
Hi,
I'm trying to use the new router, ngComponentRouter in a new project using AngularJs 1.5 and ES6.
So i downloaded it with npm (npm install @angular/router) and imported it in my app.js.
import ngComponentRouter from 'npm/@angular/router/angular1/angular_1_router.js';
console.log(ngComponentRouter) is returning an empty object {}.
Therefore i can't instantiate ngComponentRouter.
angular.module('app', [
ngComponentRouter,
....
]
);
This will return :
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module {} due to:
Error: [ng:areq] Argument 'module' is not a function, got Object
Any ideas what could be done to be able to use it?
@btribouillet You don't need to import it that way. Just import it and use the string
import 'npm/@angular/router/angular1/angular_1_router.js';
angular.module('app', [
'ngComponentRouter'
]
);
@brandonroberts Thank you! perfectly working ;).
@btribouillet :+1:
I talked to fast ;).
Actually i'd like to inject it in the configuration of my module.
import angular from 'npm/angular';
import 'npm/@angular/router/angular1/angular_1_router';
import uiRouter from 'angular-ui-router';
import homeComponent from './home.component';
let homeModule = angular.module('home', [
uiRouter,
// 'ngComponentRouter'
])
.config(($stateProvider) => {
// .config(($router) => { // Using ngComponentRouter
console.log($stateProvider); // return the stateProvider object
// console.log($router); // Using ngComponentRouter
// $router = [
// { path: '/home', as: 'Home', component: homeComponent }
// ]
})
.component('home', homeComponent);
export default homeModule;
The commented code is the code i'd like to use (using ngComponentRouter) but returning Unknown provider: $router. This code is working with ui-router.
Am i wrong to inject $router instead of something else?
@btribouillet you don't configure routes in the config phase using ngComponentRouter. You have to inject the router into your main app controller and configure them there. Check out this app.js from a sample repo I have.
https://github.com/brandonroberts/angularjs-component-router/blob/master/app/components/app/app.js
Perfect! This is exactly what i needed. Thank you again.
@brandonroberts thank you for the details, i've got it working as well
it's worth noting you'll need [email protected] < [email protected] for which you will get npm install issue as of this moment, but you're still able to execute the gulp task to build the ng1 router
@oknp good to know. Thanks.
@brandonroberts Great work and thanks for all the helpful info. I've gone over your GitHub project, but I'm trying to use Browserify to require
in ngComponentRouter in. To this end, I've published a package on npm (https://www.npmjs.com/package/ngcomponentrouter), wrapping the router as a compatible module. I also have a test project that uses this package, here: https://github.com/duluca/angular1.5-starter. However I get a runtime error saying TypeError: Cannot set property '$$currentComponent' of undefined
. Any ideas on what may be going wrong here?
@duluca there are some issues.
require
statements in the angular_1_router.js
file to require1
. Some of the directives use require
in their directive definition object, so you'll need to change those back.name
in order to link to them.ng-viewport
in the ngComponentRouter. <a ng-link="['Home']">Home</a>
I hooe this helps.
@brandonroberts That was very helpful, thanks. I think I fixed the issues with the npm package (https://www.npmjs.com/package/ngcomponentrouter), and I've updated the GitHub project with your suggestions (https://github.com/duluca/angular1.5-starter).
The landing page renders properly now, but when I click on Home
I get a different error StringWrapper.charCodeAt is not a function
. Any ideas on that one?
StringWrapper.charCodeAt has a pretty simple implementation. It should be something like:
charCodeAt: function(s, index) {
return s.charCodeAt(index);
}
Thanks @thegrtman. Yeah, looks like https://github.com/angular/angular/blob/2a2f9a9a196cf1502c3002f14bd42b13a4dcaa53/modules/angular1_router/lib/facades.es5 is missing the implementation
Yep. It's missing from the facades included in the ng1 build
On Jan 23, 2016 11:19 AM, "Kevin Groat" [email protected] wrote:
StringWrapper.charCodeAt has a pretty simple implementation. It should be
something like:charCodeAt: function(s, index) {
return s.charCodeAt(index);
}—
Reply to this email directly or view it on GitHub
https://github.com/angular/angular.js/issues/12926#issuecomment-174202546
.
I'll send in a pull request
Good luck :+1:
On Jan 23, 2016 11:26 AM, "Doguhan Uluca" [email protected] wrote:
I'll send in a pull request
—
Reply to this email directly or view it on GitHub
https://github.com/angular/angular.js/issues/12926#issuecomment-174205299
.
@brandonroberts The latest build doesn't seem to work with the crisis and Heroes repo you posted. I know $router was renamed to $rootRouter in the code but even fixing this it didn't seem to work with the latest build
@Rab815 I haven't posted a crisis and heroes repo. Are you talking about this one: https://github.com/petebacondarwin/ng1-component-router-demo ?
Sorry it wasn't a repo you posted but this is the one I was talking about.
https://github.com/petebacondarwin/ng1-component-router-demo
I didn't know if this version of the router was adjusted specifically to work with components cause I can't get the latest build to work with it
@Rab815 you have your own build or are you using the one from the repo?
I downloaded the one from the latest npm @angular/router
@Rab815 that's a very old build that hasn't been updated yet. You should use the one from the repo you've posted until the npm repo is updated
There was a notice that npm was updated within the last 24 hrs. I'll try to get one from angular2 dist folder or clone the angular2 repo and build it from there. Has the router been changed from $router to $rootRouter in the angular 2 repo. That seems to be where the dev for the angular_1_router is taking place correct?
@Rab815 I see. I had to specify a different version to get the most recent one from npm
@Rab815 the $rootRouter changes haven't been merged into master yet, which is why the npm build doesn't work with the repo
@brandonroberts ahhhhhhh, so why is the one from that particular repo the one that seems to work with .component based link targets? just curious... trying to figure out how to keep working versions and know when to pull the latest version. It's quite confusing! Thanks for you help on this so far
@Rab815 that's because the repo belongs the lead developer of Angular 1. I think the component router will be officially released soon, which is why the repo is being updated. Once its released the npm repo will be the official source for updates.
@brandonroberts so is that the ngComponentRouter npm repo or the @angular/router npm repo? I.e. Npm install @angular/router. Or. Npm install ngComponentRouter
@angular/router is the official one
Thank you sir! I will watch that one for updates and in the meantime use the one in the crisis/heroes example that was posted. I appreciate all the helpful information
:+1:
@Rab815, there was indeed a new version released (v0.1.0
), which should be compatible with components. It is currently labeled as pre-release
, so you probably got the old 0.0.1
version (if you did npm install @angular/router
).
You can (as a temporary workaround) try npm install @angular/[email protected]
.
Does it also address the issue of not finding the html template for a component when not using the template: property. I attempted to use .html files with the same name as the component but it would find it unless you use the templateUrl property explicitly
Not sure about that. /cc @petebacondarwin
Yes, the 0.1.0 version does indeed work with templateUrl
!
@petebacondarwin Yes I know it works WITH templateUrl
. But I thought previous versions would find the html files with the same name as the component by default. I.e. ./component/home/home.html if the component was named home and in home.js, without the need to explicitly use templateUrl
. That it would find the template based on conventions. A previous version also seemed to have an override capability using $componentLoaderProvider to tell it where the templates were should the directory structure not follow convention but I don't see an equivalent in the more recent versions. I could be wrong, I may have misinterpreted how it would work, just asking for clarification. Thanks for your help!
Yes all that has been removed. This was from when the ng1 component router didn't actually route component directives but controllers with associated template files. It was all rather magical.
Now we have a much more solid API based around component directives, which is much more similar to how it works in Angular 2, as well. Give it a try.
Ok I'll try downloading the latest from @angular/[email protected] and try that. Should I have issues maybe I'll try posting a github to see what I'm doing wrong. Thanks for all your help!
@petebacondarwin or @brandonroberts ok, I've got a plunker set up with the structure I'm working with in order to break components into separate directories. My question is, isn't the home or welcome component supposed to be able to find the location of the welcome.html or home.html templates based on convention instead of having to use the templateUrl:
in the component options. This is using the latest anuglar_1_router.js. If I comment out the templateUrl in each component everything goes blank
No we don't use loading by convention
ahhhhh.... so either a template: or templateUrl: must be provided. Thanks for the clarification sir! Much appreciated. Least I'm heading in the right direction... how I wanna work on requirejs to load the component js files when they are needed vs loading all the js files for the application on the index.html page
We are looking into lazy loading. It will be available in Angular 2. There are some difficulties with Angular 1, since it is not designed to support late bound components. There might be a way to get it to work with one of the 3rd party Angular lazy loading modules, and AsyncRoute
routes.
I got lazy loading working with https://oclazyload.readme.io/ a while back. I'll see if I can get a small plunker together.
I was just looking at oclazyload... but I wasn't sure based on the examples if it would work with the new router since it works without static routes in a routeprovider... the config looks different. any help is always appreciated.
Right. You wouldn't be able to use the static $routeConfig in the component helper with it. You'd have to inject the $router into your main component and setup the routes that way. You could use it in a run block also.
@Rab815 here is a simple example of lazy loading using ocLazyLoad and the component router. The About
route is being lazy loaded through a separate module.
Cool! Thanks, I'll try integrating that approach into my plunker.... see if it works out
http://plnkr.co/edit/xlOnWRomoXfPEPzFKgFu
@brandonroberts I integrated that in with my plunker but it still seems as if it's loading the js files before it needs to... does this know to unload js files that it no longer needs? I integrated what you showed me into the appModule.js file and took out the load
@Rab815 you need to remove appModule.js or anything else you want to lazy load from your script tags. That's why its getting loaded before it needs to. From docs it says:
There is no way to unload javascript, but you can remove css by deleting the link tag of your resource with something like that:
@brandonroberts Actually I take that back... when I look under sources in chrome under run.plnkr.co
the home.js or welcome.js isn't getting loaded until I click the links... Thanks! Hopefully I can refine this a bit as development goes.
Great work you two. Perhaps one of you could write up a blog post about how to get this working?
@petebacondarwin The only problem with this plunkr http://plnkr.co/edit/xlOnWRomoXfPEPzFKgFu?p=info is that the loadmodule function has to be in scope inside the run function and for components with subroutes its a lot of repeat code. Might have to put that in a service or another module that can be injected but still be used within the run function. Also with this route.config{} it doesn't seem practical for large enterprise applications. Also trying to figure out a way to create some kind of dynamic routing mechanism based on variables ie.. /app/:module/:component/:params* then fill in those blanks so it can find the right component. But with the route.config{} occuring in the run phase it may make this much more difficult. Overall I'm trying to figure out a way to do dynamic routing / on demand resource loads. Please let me know if this approach isn't to feasible given the way the new routing mechanism works... perhaps my goals are a bit lofty
:+1:
If any of you is able to make a good working plunkr, let me know and I'll add it in the documentation of ocLazyLoad :)
Is lazy loading still planned eventually for the component router? Using third party hacks like my overmind and @ocombe's ocLazyLoad was fine as a temporary stop gap but far from ideal.
At least some methods inside angular could provide a much better solution for lazy loading components, even if it's not officially supported.
@petebacondarwin do you want us to work on that ? We could do a PR
@ocombe I have working plunker here using your lazy loading. If you want me to clean it up visually I can. http://plnkr.co/edit/f40DUTysEFuj4L74U5BO?p=preview
I think it's fine if Angular doesn't include the functionality for doing the actual lazy loading itself, people can use webpack or requirejs or similar for that. I just want Angular's injector to not expect everything up front so it's not impossible to do.
One core tenet of Angular is that it gets out of your way if you want to replace parts of it. Lazy loading however is one area where Angular is the only framework that gets in your way.
@brandonroberts I was trying something very similar to your plunkr but I was trying to just put the loader in another module called lazyModule with a publicly accessible function
@Rab815 putting it into a service seemed cleaner and more reusable. One limitation is that the nested child routes aren't able to be lazy loaded since they are expected to be defined once the parent route is loaded.
@brandonroberts Here is the version I came up with... it places a $lazy on the only global variable mainapp but loads everything in a module... I don't know what the benefits or pitfalls are on the implementation compared to yours... it's just what I thought of. What I was trying to achieve was a simulation of the components, modules, etc broken into separate directories. maybe overkill
One core tenet of Angular is that it gets out of your way if you want to replace parts of it. Lazy loading however is one area where Angular is the only framework that gets in your way.
Agreed @geddski, just tweaking a few things would make lazy loading a lot easier
just tweaking a few things would make lazy loading a lot easier
If tweaking those things doesn't "hurt" the codebase in other ways (or if the benefits out-weight the drawbacks), I don't think anyone would mind enabling lazy-loading in ng1.
It's not like it hasn't been brought up before (e.g. #11015 and #4694).
If it's not a massive change (and from the previous comments I understand it isn't), then a PR is always a good way to get the conversation started :smiley:
@gkalpak the conversation started a long time ago. People like @ocombe and myself built third party hacks to work around Angular's design limitation when it comes to lazy loading. We had a very lengthy discussion over a year ago with the Angular team about how Angular plans to pave this cowpath that the community has been asking for. Plans were made for this to be part of the component router in 1.4. Then it slipped to 1.5. Now lazy loading appears to not even be in the feature set. So please understand that your comment about submitting a pull request to start the conversation feels a bit patronizing.
@geddski, I'm well aware of the conversations (and the outcomes) :grin:
My comment probably didn't sound the way I intended it to (I definitely didn't mean to sound patronizing). It was more of an affirmative answer to @ocombe's comment:
At least some methods inside angular could provide a much better solution for lazy loading components, even if it's not officially supported.
@petebacondarwin do you want us to work on that ? We could do a PR
So, I was referring to a PR about _making lazy loading a lot easier_ (even if not officially supported or available in core). And I'm pretty sure both you and @ocombe have better insights about lazy loading in AngularJS than you had _over a year ago_.
Anyway, I definitely didn't mean it in anything but a good way.
tl;dr
If you think that tweaking a few things in core would make it much easier/saner for 3rd-party modules to provide lazy loading (or provide _better_ lazy loading) and have interest in submitting a PR, please do :smiley:
@gkalpak got it, my mistake :)
@geddski, no worries ! I could/should have been more clear :D
@petebacondarwin @ocombe @Rab815 I made a blog post detailing how to use lazy loading with the component router. If you see any major issues, let me know.
https://medium.com/@brandon.roberts/using-the-component-router-in-angular-1-lazy-loading-a8258fcdb8cd#.4tofx9ga4
@brandonroberts Thank you very much! Maybe the blog post should include how to install ngComponentRouter in Angular 1.5, (Is it officially supported in Angular 1.x? Estimated release time?). There are a lot outdated information and confusion with the new router, specially for newbies like me. Great work, thank you guys.
@hacknaked the component router isn't officially released for Angular 1.x yet but I think it's pretty close. Once it's released I'm sure there will be a blog post detailing how to install it and more samples on using it.
@brandonroberts are there any examples of accessing param values? I.e. my route is /user/:id , how can I access the :id value in a component (specifically the controller)?
@nicl there currently isn't a public way to access the params in the constructor. What you would need to do is use the routerOnActivate
method and get the id from next.params.id
There is an example in Pete's repo here: https://github.com/petebacondarwin/ng1-component-router-demo/blob/master/app/heroes.js#L80-L95
If you look at the HeroDetail
route you see it has an :id
parameter also.
@nicl also it doesn't strictly make that much sense to access the params in the constructor since the component could be reused. That is why we have the various hooks: $routerOnActivate
and $routerOnReuse
@brandonroberts @petebacondarwin the $routerOnActivate
method doesn't work with the templateUrl
property, only with template
. Wasn't this fixed at some point? I remember reading somewhere about it.
@andreiho There is a PR for it here: https://github.com/angular/angular/pull/6978, it just hasn't been merged in yet.
@brandonroberts Oh right, I saw that at some point, just couldn't recall.
Hopefully @matsko will merge that today.
@brandonroberts @petebacondarwin thanks for the help and example project!
@andreiho I was experiencing this issue so good to know :)
@nicl just for the record, until the fix for $routerOnActivate
is merged in, you can also access the params by injecting $router
in your controller and getting the params from $router._currentInstruction.component.params
.
@andreiho that only gives you the root router though. I'd stick to getting the params through the routerOnActivate hook
It appears the PR was finally merged in, so I went ahead and built the router to fix the issue with lifecycle hooks not working with templateUrl
.
Gist: https://gist.github.com/andreiho/abc94a492c5986678385
$router
was renamed to $rootRouter
, so remember to update all references.
@petebacondarwin @brandonroberts is there currently a way to access the params inside the $canActivate
hook? Does it even make sense, lifecycle-wise?
Since canActivate is invoked by the injector, the instructions are passed as "locals", which can also be injected...
function $canActivate($nextInstruction, $prevInstruction) {
var nextParams = $nextInstruction.params;
}
See https://github.com/petebacondarwin/ng1-component-router-demo/blob/master/app/crisis-center.js#L28
(By the way, I think we ought to rename that hook to be $routerCanActvate
inline with the other hooks.)
@petebacondarwin Thanks, didn't think of that.
(And I agree it would be a good idea to rename the hook. That's actually what I tried initially and couldn't figure out why it wasn't working, so I had to go in the source file and find how it was named)
Is $canActivate
supposed to be usable as a component option? Because it never gets fired here:
angular.module('myApp').component('app', {
template: '<ng-outlet></ng-outlet>',
$routeConfig: [
{ path: '/', component: 'home', name: 'Home' } // works fine
],
$canActivate: function($nextInstruction, $prevInstruction) {
console.log('I never fire. :-( ')
},
controller: function() {
}
})
EDIT My mistake, I guess you can't put $canActivate
into the the same component which is defining your $routeConfig
. I moved $canActivate
into one of my child components and now it's apparently working.
Yes the $canActivate
must currently appear on the component _being activated_.
There is some discussion about all this at the moment and is subject to change: it is likely that we will make it so that the parent component/router is responsible for deciding whether a child route can activate.
Is ng-link-active
class actually working? If so, how it works?
@diegohaz yes, its working. The ng-link-active
class is added when the current route matches the route provided in the ng-link.
But it has not yet been released in version 0.2.0 of the router
@brandonroberts @petebacondarwin I see. Thank you. By the way, where can I post issues about the ngComponentRouter for Angular 1.x? I want to know if it has support for states/sibling views.
@diegohaz you should file those here: https://github.com/angular/angular
Actually for Angular 1.x you can start posting in https://github.com/angular/router
I am rebooting that as the holding place for the Angular 1 Component Router.
(Still a WIP but should be the place to go by the end of the month)
so with the recent changed to angular2's gulp file, gulp buildRouter.dev
doesn't work anymore.
what's the offically recommended way right now to get the component router working in angularjs 1?
@geroyche there is currently no recommended way as the router that we did have is no longer compatible with the latest router for Angular 2, and the old router has outstanding bugs that will not be resolved.
We plan to port the latest router to Angular 1 over the summer but there are technical hurdles to overcome around bundling, DI, Zones and Observables.
that's a bit disappointing to hear, since it was communicated as a best-practice approach to use the component router in angular1.5 projects in order to ease a future migration to angular2 (we already switched from "angular-new-router" to the "angular1_router" backport).
guess we'll have to wait and see.
I am sorry and I understand your disappointment. We are working hard to get this fixed for you but we have limited resources and are being pulled in lots of directions. If there are people in the community who want to get involved in working out how to port the router (and the http library) then I would love to get in touch with them.
Also worth noting that ui-router supports both ng1 and ng2, as well as hybrid ng1/ng2 apps
true. we specifically chose not to add another dependency, ui-router, based on the notion that the new angular router(s by now) would fix the shortcomings that led to ui-router's existence in the first place.
but yes, maybe we should reconsider.
npm install "@angular/router": "^0.2.0" -D
import Route from '@angular/router/angular1/angular_1_router';
Most helpful comment
Also worth noting that ui-router supports both ng1 and ng2, as well as hybrid ng1/ng2 apps