JOHN:
Hey, guys, did you know Jeff Goldblum is on this call?
[Does your team need to master AngularJS? Oasis Digital offers Angular Boot Camp, a three-day, in-person workshop class for individuals or teams. Bring us to your site or send developers to ours -AngularBootCamp.com.]
[This episode is sponsored by Wijmo 5, a brand new generation of JavaScript Controls. A pretty amazing line of HTML5 and JavaScript products for enterprise application development, Wijmo 5 leverages ECMAScript 5 and each control ships with AngularJS directives. Check out the faster, lighter and more mobile Wijmo 5.]
CHUCK:
Hey, everybody and welcome to Episode 31 of the Adventures in Angular Show. This week on our panel, we have Joe Eames.
JOE:
Hey, everybody!
CHUCK:
John Papa.
JOHN:
Hey, everybody, from sunny Florida.
CHUCK:
Lukas Reubbelke.
LUKAS:
Hello from sunny Phoenix, Arizona!
CHUCK:
Ward Bell.
WARD:
From frigid San Francisco, where it's 69°F.
CHUCK:
Oh, poor thing. I'm Charles Max Wood from devchat.tv. Before we get going, I wanna make a quick announcement and then we'll announce our guest. I'm putting together a Kickstarter campaign kind of to help support the shows that we do at devchat.tv. In particular, though, it's a video series, a screencast series on how to do stuff Ruby on Rails which may or may not be relevant to this show depending on what you use on the backend for your Angular app, but regardless, if you wanna go support the show, there are support levels for all different types of people. Some of them include some of my time for coaching or in-person training. So if you wanna go check it out, you can go to devchat.tv/kickstarter and just check it out. I really appreciate the support.
This week, we're going to be talking about the Angular UI Router and we have a special guest to talk to us about that, that’s Craig McKeachie.
CRAIG:
Hi, everyone!
CHUCK:
Craig, do you wanna introduce yourself really quickly?
CRAIG:
Sure. I'm probably best known for writing the JavaScript framework guide, a book that covers Angular, Ember and Backbone and kind of compares and contrasts them and helps you kind of learn them at once. But I also do Angular training and so I'm here. I'm glad to be here.
WARD:
That’s cool! And you're here to talk to us about routing. How do you get into that?
CRAIG:
[Chuckles] That’s a pretty open-ended question. Sorry, you threw me a little bit off there, Ward. [Laughter]
LUKAS:
He does that.
WARD:
I don't wanna ask you true or false questions. Craig, [inaudible] routing is a really bad idea -- true or false?
CRAIG:
[Chuckles] No, I listen to the show and I heard on a past episode, I forget which one it was, but you guys had mentioned, “Hey, the UI Router, in particular, routing in Angular deserves its own show,” so you know, I reached out to Chuck because I've been on a couple of the other podcasts and said, “You know, I recently wrote a blog post on this. I had trouble kind of wrapping my head around particularly the UI Router, but I'm kind of a big fan now.” And so you know, I just said, “Hey, why don't I come on and talk about it?”
JOHN:
Hey, Craig, you know the questions only get harder from here, right? [Laughter]
JOHN:
“What is your name?”
CHUCK:
“What is your quest?” Oh, sorry, wrong show.
JOHN:
So I'm curious on this because like, I know that you're famous for your book and I think that’s awesome the way you compare all those frameworks, but how do you feel about the routing situation? I think some people don't understand when they come into it that a router’s almost an essential piece of it. You can’t build [unintelligible] that one, but what do you think about that?
CRAIG:
Yeah, and I think a lot of the examples, particularly with Angular because it's really easy to show that the data binding example without even creating a controller or a router or anything. And people sometimes, that’s the easy thing to demo, so they tend to show that. But really, when you're building an app, you probably wanna think about your routes first, or at least the virtual pages or views you have that you're going to transition in and out of, so I definitely think it's important.
WARD:
So tell me what you think are the sort of essential characteristics of a router?
CRAIG:
Well, I think I've seen sort of two generations of routers out there. So the first generation is where I would see some of the essential characteristics. So at its base level there it's, “Here’s a URL, map me to a block of code that needs to run when I go to this URL.” And usually, with a single page application, that URL mapping to code, that code does something like instantiates a controller and marries it up to a view or a template and renders that into the UI. And so I see that as the basic functionality; the ability to when you go to a given URL, to sort of handle that transition between what I like to think of virtual views. You’ve got your single page, but you're actually transitioning in different templates into the view to give sort of a virtual page loading experience to the user.
WARD:
So it's some kind of marrying of the URL to navigation, where navigation leads to dynamic view composition. Is that kind of what you're saying?
CRAIG:
Yes, exactly.
WARD:
So let me throw a hard one at you: why the emphasis on the URL? I mean, I get it for a web page because there's really no other way to get around the browser, but if you think about desktop apps, then don't even have the notion of a URL. If you look at mobile applications on our phone, they don't have a URL, yet all of them have navigations. And if we had a banking app, right? If I had a banking app, it's not like I wanna have somebody have a deep link into my checking account. So what do you think about that question? Why is the URL so central to this notion?
CRAIG:
I think it is important. And yes, there are instances where the URL is less important or particularly, as you kind of drill down into different states or different levels in your application, it may be overkill for you to have every single sort of transition and state in your application to be a URL. So you know, you can take too far but I think it's important. For example, the exact example you gave, “I wouldn’t wanna link directly to an account in my bank.” And I would argue, “Well, maybe you would.” I think that would be a useful thing to get an email that says, “Hey, it seems that you had an overdraw on this account.” And there's a link in the email to that account. Now, of course, when you hit that URL, you would wanna authenticate the person first and then redirect them to that page that’s still behind a login but you know, how are you going to send that email someone and get them to the right place? You just want them to always login to the app and then hunt and peck their way around to find something? I think… I would argue not.
JOHN:
I think that the things are changing in routing recently, than it used to be just deep linking in history, but now it's becoming more about composing the app, I think. So not just having a route go from an address in the URL in the browser and linking it up, but also having different parts of the page, areas that [unintelligible], which can then be composed based upon routes or sub-routes or states if you use the UI Router. By the way, I wanted to mention that I think what you just designed, Craig, was a phishing scam for bank accounts. That's all I could think about when you said that. [Laughter]
CRAIG:
[Chuckles] That’s an excellent point. I think there’s lots of time when you wanna deep link into an app and make it convenient. Maybe the banking app, I was being hung out there to dry by Ward.
Thanks, Ward, by the way.
JOHN:
Yeah, I agree. I think he set you up on that one. [Laughter]
WARD:
But you know what, I thought your come back was really terrific because I’m sitting here saying to myself, “You know what, that’s a good idea!” Like, I f there's a problem with a particular deposit, why should I have to work my way through the history if you can tell me? And you got me on my heels there on that one, because I thought, “A-ha! I got them. Nobody would want that,” but maybe you got a point. It's just that coming from the desktop or… in a world where there are no URLs, the question is I had a client who refused to use controllers over the router precisely because they wanted nothing to do with the idea that somebody could link in. They wanted then to March their way through the user experience to get there and they still wanted dynamically composed views and navigation, but they didn’t want the URL to participate in it. And there seems no way, in today’s routers, to be able to say, “I wanna be able to do application navigation independent of URL change.” It just doesn't seem to be an option. And I guess it's the lack of that option that’s got me on my heels.
CRAIG:
Yeah. But I'm kind of like the way John was taking us there with composability story because I think there is that sort of second evolution. I think we could talk about the whole URL thing, is it important or isn’t it important for a while, but I think reasonable people would agree and disagree on that. But I feel it's a more important point the way routers are evolving to this composability story, but I'll leave it up to the floor as to where we head next to.
CHUCK:
Yeah, well if you hate your users, then definitely leave the URL out.
WARD:
[Groans]
CHUCK:
No, really though. I think we've kind of trained ourselves over the last 20 years, 30 years of having the Internet that the URL is kind of is the way of accessing the resource. And so, I like the idea of coming in on a single page app and being able to easily get where I wanna go, and to that degree, then maybe I don't need the URL to update. But I really feel like (and this is the point that Craig made), but you know, if I'm like dealing with particular instance of something. And definitely, I want to have a resource listing that I can go and hit and work on. If it’s a complicated workflow, you also want them just so that people don't have to waste a bunch of time getting to where they need to be.
WARD:
I hear you, but there's no such corollary within native mobile applications…
CHUCK:
That's true.
WARD:
As a matter of fact, in many other design languages they won’t even let you do it. You’ve got to go the way they say. I know that was originally true in the Windows design language. It was very constraining and I thought that was true in all Windows phone. But I think it was true across the native mobile apps where there's just no notion of a URL -- you navigate according to the way they tell you to.
CHUCK:
That’s true.
JOHN:
So I think routing is an interesting point too in this because if you look at it, it solves a problem that you can solve (as Craig alluded to earlier) using ngInclude, custom directives or your own custom composability techniques. So, why… I guess this goes back to you, Craig, when do you tell somebody to use UI Router as opposed to doing custom directive or an Include or maybe an ngSwitch even?
CRAIG:
Well, the short answer is all the time – no I'm just kidding. [Chuckles] But honestly, like business reasons would be there's two that I outlined in the post that I think after reading a lot of stuff, and the one that actually comes from an argument that the Ember framework uses to sort of compete against the Angular framework, and that is the ideal nested routes.
So the idea of a nested route as you know, when I interviewed Tom Dale who's one of the creators of Ember for my podcast, he basically was the first person who kind of made me aware of this; this idea that you have a list, let’s say it's a list of blog posts and you click on a blog post in the list and then you wanna show the detail of the blog post, you know, the content of the blog post but you wanna keep the list on the page. And that’s the idea.
So you have the list, say, on the left hand side of the page. When you click an item, you see the detail on the right hand side. And you can even take this one step further as they do in Ember’s classic blog example is then you edit… you might wanna edit that detail so you might have an edit link, in the detail, you click “edit” and a form appears. And it might be reasonable for when you want to deep link into any of those states and have all that to basically have the list and have the detail on the page at the exact same time. And so that’s that concept of nested views.
So people don't get confused in Angular 2.0, this is referred to as a “child route”. So you'll hear “nested views,” you'll hear “child routes.” I believe there's one other term I've heard before, but most commonly, “nested” is the term people use for this idea. “Master-detail” is what we might know it as from, you know, older application building paradigms.
JOHN:
So that's a great point, “nested routes.” Now, when I first heard of nested routes, one of the things I've found is when I started explaining it to people, they were all confused (in some cases, maybe it's just me explaining it, very likely) but think about a nested route; what we're not saying is that when you go down this route, like a customer detail, customer list or whatever else it might be, you're not going to have different URLs for every route showing up at the same time. Meaning, you could have four routes, different states on the screen with an Angular app with nested routes and other routes, but only one of them is actually married to the address bar. And I think sometimes that can be confusing for people, you know? What's happening here? How can you possibly have two routes at the same time? How do you explain that to people in a clear way?
CRAIG:
That's a good question. I think it's easy to think about, for me, when I have a concrete example like the one I just gave, where you want two elements to show on the page. Now, granted, you could achieve that example I just said, the least list detail example by simply hiding and showing the detail on the page, using like an ngClass or something. But I feel like that’s not very elegant because as I show in examples when I'm training and so forth is that the great thing about using a nested route for that scenario is that you can break the code for the list and the code for the detail, each have their own controllers, their own views or templates and it's sort of encapsulated or isolated separately.
So I feel like that’s the big win is when you can have that composability story and you could pull those back apart and have just a list just on the page. And then when you click on an item, it goes to a detail page that just got the detail or you can bring them together. And you know, it takes a few lines of code because you’ve constructed it in a composable way. Although, John, I'm not sure I really answered your question there, so maybe somebody else can give a try on that too.
JOHN:
I think what you did is you kind of answered it the same way I did, which is it's not an easy thing to describe. It might be better with visual representation, you know when you're showing different zones in the screen with different routes all rendering. Because every time I've just explained it verbally, I think it gets confusing to think, “Well, how come you have four things that all point to the same address bar?”
CRAIG:
Yeah. And I guess one kind of way to think about it is you're building on to the URL, so you start where the URL might just say “/list” and then it might say “/list/detail (with an ID on the end)”, eventually. So you're kind of nesting down if you think of the URL as it gets longer as being nested inside of the prior sort of level of the URL, then you know, you're creating this more of composable… you're composing the URL at the same time as you're composing the screen. And the advantage of that is simply that you can either deep link to that any of those states, or you also the “back” button won’t break at any of those states if somebody hits the back button and expects to go… they go to list, they go to detail, they hit the “back” button, they expect to go back to the list, that will work with the sort of nested route example. And likely won’t work if you're just hiding and showing things.
WARD:
So I'm still struggling with this myself, so let me try this on you and see if it's true. Because I had the same problem that everybody else has with this. Like, how can I have a single URL represent say three things? So the way I sort of come to it is I think of it as each of the segments of the URL represents a state in the hierarchy… so let’s take your thing, it goes “Blah blah blah list” So let’s suppose that’s… well, “blah blah blah” is the outer one and then there's list which is a… so I have an outer state that’s the “blah blah blah”, right? Is that fair? Like an outer box?
CRAIG:
Sounds good.
WARD:
Then I go “list” and you say, okay, so that’s a box inside the list area, inside my “blah blah blah” box. So I've got a box in a box. And then you go “/detail one” and that’s a box inside that box. Can I see it as sort of boxes and boxes and boxes? Is that fair?
CRAIG:
I like that analogy.
WARD:
Okay, so then if each box is responsible for itself, I guess I can understand that the “blah blah blah” describes the state of the outer box and it maintains that state. And then as soon as I went inside, I didn’t actually have to lose that outer box, right? In other words, that all that state that represents the outer shell there is still operative. It didn’t go away. I simply added new stuff that went into that inner box. Is that true?
CRAIG:
Correct. So you're composing, right? You're just adding to that inner box. And I think when you talk about boxes, that's a nice transition into the other advantage of using something like UI Router which is with the built in router in Angular, (I’d say built in but it's actually, it's in the Angular project now but it's been pulled out as a separate download basically, so like ngAnimate or resource or something like that, so you have to include an extra script file), but to get to the point, there's a tag that you put on the page that basically are directive (in Angular terminology) that says, “Here's where I want you to place that new view – that virtual page or that new page that you're loading into my single page -- and that tag is called “ng-view” within the ngRouter.” There is a limitation with that router, (the new one that Angular is coming out with does not have this limitation) that there can only be one ng-view directive on a page. So this is where obviously then, you can’t nest views. You can’t put an ngView with another ngView nested inside of it.
And furthermore, the other advantage of it is you know, it's very common to have sort of a header on a page and a footer and a main content area and maybe a side bar or two. And each of these areas ideally, at least for me, I’d like that code sort of encapsulated in its own controller and own view template and so forth. But since you can’t have multiple… what I call “multiple views” on the page, that’s the other thing that Angular UI Router allows, so nested views and multiple views. So the multiple views I like to think of as having a home, header sort of view and then a footer view and a side bar view and a content view, if you think about page being split up in the boxes (to carry your analogy on.) So you can either nest those boxes but you don't need to nest those boxes. But the draw of the UI Router is that you can have more than one box on the screen at a time.
WARD:
And you're going to let the router define what those things are that are going to be on there because if I didn’t have that, right? If I didn’t have that feature that you're describing, then the outer controller would have to place those things in all by it's lonesome.
CRAIG:
Sometimes what you end up with, if you didn’t have that, is you end up with maybe a template that’s got… it has many responsibilities if you think of template that has a single responsibility or a view that has just a single job. You end up with these views that are doing multiple things like controlling the navigation as well as still rendering the content on the page and so forth.
WARD:
Right. [inaudible] With ngIncludes, right? We would just say ngInclude header, ngInclude footer and then we would reserve the one area in the middle for the dynamically controlled view. And it could get complicated, yeah.
CRAIG:
Right. And ngInclude would work, but that code that if you do anything dynamic in that header, (the navigation let’s say is in the header), if you do anything dynamic that are like trying to keep the active state, which tab is active or which [inaudible] in the nav is active, that code tends to, (there’s other ways around this) but it tends to leak and get repeated in your controllers or throughout your application. Whereas if you have that kind of just code that runs and it's only job is to maintain that navigation, that’s kind of nice to have that isolation.
CHUCK:
So I was a little bit confused about why you would use this but I'm kind of getting the picture now, and I wanna just make sure that I understand. So for the most part, I think people generally just use just whatever workflow you hand them. If you're doing like blog post and you have a list of the blog post on the site, people are just going to go with it because that’s where they wind up. And so, where this really works out is if you have a complicated layout that has multiple areas that can all be updated in different ways. And so people can navigate to more of a complex set of views or selfviews inside of the main view, that this could get them back to exactly where they were because it tells in that route then, it tells where all of the different views were when they left. Does that make sense?
CRAIG:
I think that’s a good summary, yeah.
WARD:
Yeah. Let me see if I've got the same insight you have, Chuck, or maybe it's just the thing that stood out for me about the difference between a regular one and this one. I mean, the regular one, you know, you can only get one, so if you're going to have any complex structure, you got one place to make the change. And every time you change the URL, it's got to recompose everything all the way down and it loses all the state all the way down from wherever you start. I think that’s true of the Angular’s own router.
But as I understand it, (tell me if I'm right, Craig) with the UI Router, let’s suppose I'm just changing the URL to change some one small box deep down in that nested structure, I can do that without having to reconstruct all the outer pieces, all the outer containers and have them rebuild all their state and all that other stuff. I don't have to do that. All that state is just there. And so that move to that deep down, inner URL that’s dealing with some small part of the real estate on my screen, it only has to change that state. Everything else is going to stay there for me. Is that fair?
CRAIG:
You know, you're causing me to think pretty hard about whether that other code that’s the beginning of the URL re-runs. And I think it kind of has to do with how you coded it, but my gut is telling me from what I understand is that that code still re-runs. It's more about, “Did you keep track of where you went?” Did you leave the bread crumbs behind you so that you can get back on the trail where you came from? So it's not about performance as much or not re-running code; it's about code maintenance and about code being isolated in a place where it makes sense. And then it's also about keeping a trail through the actions that you took, so that you can make it back to any specific state, any specific path you took on your journey to get where you are in the app.
WARD:
Let’s put a pin in that because I could swear that was true. For example, take your list detail, right? And you have the list on the left had side and every time you click a detail that's a new drawing of the detail area on your screen, right? In you master detail…
CRAIG:
Mh-hm.
WARD:
And I could swear, because the list in the outer one, it's in the outer part, that higher level state and then the detail one is the next one down and inside, I could swear it wouldn’t cost me to re-draft the list and repopulate the lists. Because that was in the outer state, I could count on that still being there untouched and…
CRAIG:
Oh! I see what… I think it's nuances here. We might be saying the same thing. So if it's just about the data, “Do you have to go back out and get the data again?” The answer is, “No, you don't have to go back out and get the data again,” right? You could just share that with the child controller. There's ways to do that. But if it's more about, “Does that controller that builds up the outer view when you go to that new state, does it get re-instantiated?” That’s where I think, you know, maybe the template gets re-rendered and the controller gets re-instantiated as you transition deeper and deeper down into the URL. Does that make sense?
WARD:
It does, but I have a different recollection, so we're going to put a pin on that and come back. [Laughter]
CRAIG:
Yeah, I'm obviously not sure of this. But yeah, I think the important point is you know, I see the benefit as being, the composability story regardless of under the hood, whether there's some performance impact. I think it would be a minor one, you know. I guess you could argue there's scenarios where that wouldn't be the case, but I think the important point is you do not… you have one ngView per page when you're looking at… using the built in router in 1.2 or 1.3 of Angular.
And just to be clear here, the Angular team would probably be remiss if I didn’t say… we'll probably get to this, but the Angular Team has a new router. They built it for the 2.0 of the framework. They're backporting it into 1.3 of the framework or maybe 1.4 now because I think they have moved to 1.4. But they are basically backporting it into the latest 1.x branch. And maybe they are already, but a lot of people, because the browser support issues are still stuck on the 1.2.
So that's where kind of I’d say use the Angular… if you're stuck on 1.2 of the framework because you need to support IE8, use the Angular UI Router. That is your best option. When you get to 1.3 and 1.4, I would look to use the Angular router because they added these capabilities to their router. They re-wrote the router basically and they added the capability to do nested routes and multiple views. They called them “child routes”. And I'm not sure what the terminology is. I can’t remember for a multiple views, but it is there. So if you're able to use the most recent version of the framework, it is rapidly getting there. I'm supposed to take a look at it and just haven’t had time to see if it’s actually been finished porting. So just to be clear, it is there. It is fixed. So this is really just about people who are in the 1.2 world.
WARD:
Right, right.
JOE:
I’d like to ask some question about like other routers, and then if you any thoughts specifically about the router for 1.4. So like routers and other frameworks, good and bad about them, things that good innovations, any thoughts there? And then also talk more about the 1.4 router and the back porting from 2.0 and what you think of that.
CRAIG:
Right. So I think that other frameworks that clearly had an impact on this being improved in Angular in the 1.4 version are Ember obviously, and Durandal. And Durandal, that most people don't know as well, but this is Rob Eisenberg, so the story goes -- to catch people up -- in my understanding, he wrote the Durandal framework, it had a nice robust router similar to Ember. Not sure which came first there, but they both had basically another generation ahead of router that supported nested routes and multiple nested views and multiple views in it. And he joined the Angular team for a period of months and worked with the Angular team on the 2.0 version of the framework. And I believe one of his big responsibilities was to work on the router. He’s at least been the public face at conferences and so for the new router. And it has this idea of an app router and child route, so it’s clearly in the same vain.
As far as what I think of the router in 1.4, I have to apologetically say that the Angular team has been proactive and reached out to me and said, “Hey, check it out. Let us know what you think.” And I've been trying to find the time take the example in my book and port it over to that, but I haven’t had the time, so I have no reason to speak. The only thing I have is looked at Rob Eisenberg’s presentations on the router and the functionality it will have. And it's clear that you know, it is these things we're talking about, that these nested views and multiple views. Nested views again are called “child views” in this new router. Is that kind of what you're looking to understand?
JOE:
Yeah.
WARD:
So, I'm a little bit curious about also the Ember one, but the thing that you haven’t mentioned, (maybe John was about to say this because John and I fought this like mad), in all the routers we had seen, there didn’t seem to be any support for page lifecycle. John, was that where you were going to go?
JOHN:
Yeah, that’s one thing I really loved that Rob put in one of his early routers. And we were working with… let’s go back in time now, a couple of years ago to using SammyJS and HistoryJS and all that. That was the first thing we were looking for to add into it is was how do I know how can I tap into before the route activates, after route activates. And then in the controller that it actually gets activated and hooked to, you know, when that controller is activated, when it's about to be activated (like a pre-check). And then Rob also added into Durandal different things like having a predeactivate and then deactivated hook.
WARD:
And why would you use that, John? Why is that important?
JOHN:
So the first thing we get… again, going back in time when we actually had hair on our heads (at least for me), couple of years ago, to having these controllers where I wanna check to see some state on the page. So let’s say I'm on a customer details page and I'm editing something and somebody routes off of it, how do I check to make sure, “Okay, before you go off of here, I wanna check with the controller on that page to make sure it’s okay before I leave.” And the event structure that’s in the Angular basic router, it doesn’t cut it. You need to have the controller have control over that (pun intended), so it can say, “Look, before you leave here, do this check and then setup flags of ‘yes, you can’ or ‘no, you can’t’.” And this was really, really important when we're doing like dirty checking on pages.
WARD:
[Like an async?] check, right, John? I mean, in other words, it's not something I can simply check and go. It's like, I have to wait for the user or something else to confirm that it’s okay.
JOHN:
Exactly! Which is why Promises and all that. It's one of the reasons that you and I call the main functions inside the controller activate and deactivate.
WARD:
And there was no obvious way to do that in ngRouter. And there's no obvious way (maybe Craig knows) how do that effectively within the UI Router. And I was wondering if Ember even has that notion. Do you happen to know, Craig?
CRAIG:
I'm not positive with this answer but I know clearly Rob Eisenberg wrote the majority of the router in the version of Angular in the 1.4 branch and then in the 2.0 branch, and it has the similar feature id. It was inspired by his past work. It was something I've heard him say on several podcasts that really he felt was really needed for the same reasons you guys just outlined.
As far as the UI Router, it has events, but the events to me feel very similar to the same kind of events that you get fired in the ngRoute, but that specific scenario you guys were talking about, I'm not sure if it has maybe one more event at the right point in the life cycle that allows you to sort of cancel--
JOHN:
I think the events in the wrong place is kind of what Ward and I fell onto. It’s while it's cool to have an event on the router saying, “Yeah, you’re about to go somewhere.” The logic that has to run to determine that isn’t usually associated with the router. So, for example, there’s two problems I have with it, and I'm kind of on a soapbox here and I apologize, but in the controller, that’s where I need to know if I should leave the page or not in the router itself. So that's like saying… you want to [inaudible] to the user and say, “Hey, you got some dirty changes here. Would you like to: save them, cancel them, stay on the page, go somewhere else, have a drink?” that has to happen in the controller – it's not a router.
And then second piece of that is they built-in these things called “resolvers” that resolves the promises into both UI Router and the Angular router. And that’s great for those, but now we're taking logic that normally would live in the controller and we're saying, “Hey, the data that we wanna actually add to the controller, let’s have the router handle getting that and injecting it on the controller.” And to me, that you're separating out logic on who's doing what now, separation is generally good, but shouldn’t the controller know what it needs and…
WARD:
Yeah, I agree. It's upside down. Why would the router know what the controller is supposed to know?
JOHN:
The router should [inaudible] this guy belongs to that… the router is a marriage counselor. It says, “You belong with that person…” [Laughter]
CHUCK:
“Marriage counselor.” I like it.
WARD:
Yeah. Totally with you, John. And so this “router first” notion which is written right through Ember, (it's one of the things about Ember I don't understand and maybe Craig, you can do it), but they see the world, (as I understand it) from the router down. And I always thought of the router as something helpful but not central to my application design, so maybe there's something wrong with me. Help me come to terms with it.
CRAIG:
You know, I feel like it's just back to that conversation we had earlier of do you buy into that notion. And I think there's a large subset of apps that are on an intranet inside an enterprise. Maybe they don't have requirements that need you to deep link to things. I still find that a lot of the apps I've built, it would be very useful to have people deep link into things. They send emails, they want the back button to work. I mean, it’s like the obvious thing to me.
WARD:
You sold me on that part, but I think that’s a different question though as to where the decision logic needs to be to determine whether you can activate or deactivate and that kind of stuff.
JOHN:
Right. The issue here isn’t so much like do you buy into URL deep linking, but more like is the router really just almost like a higher level controller or is it, as John said, a marriage counselor?
CRAIG:
Right. It's interesting that you guys really feel… to me, it may be just because I see it and I accept it for what it is and I haven’t run into this specific issue. I'm curious, were you able… because to me, you're in the controller, right? And you say “scope.on” and you wire up the event. You inject whatever state provider… let’s say we're using Angular UI route and you inject the state provider. Are you able to actually achieve what you needed but you just feel like the code is in the wrong place on the API? Or did you guys hit a road block where it was like, “I can’t achieve this. I can’t cancel this transition.”
JOHN:
The cancelling the transition is definitely is an issue. The situation that Ward and I mentioned about, the deactivate and the activate and the can deactivate, the can activate, those are methods that Rob put in his Durandal router and is getting into the new Angular one, those things are actually issues you cannot solve well in the UI Router, the Angular router today. And in fact, that’s what caused me to write a big, ranting email to Brad Green and Igor about two years ago.
WARD:
We couldn’t solve them at all, John. We couldn't do it at all. We could not implement that. The only thing you had, the only hook you had was Resolve, because that’s the only asynchronous hook in the entire routing scheme -- and that’s too late.
JOHN:
And we wrote… it couldn’t be solved with the framework. We actually wrote probably 700 lines of code to get around it to make it work. And that’s when we said, “Forget this! Let’s ask them to talk to Rob because Rob has solved this and see where it goes.” And obviously, good things came of it, but that’s when we started switching the route up and doing other things. And in some cases, we use Resolvers, which is really kind of a hack around that in my opinion. Or you can also do things like we did in local storage [inaudible], so we saved the data off in a controller on a local storage and then when you leave, you don't have to ask the user, “Hey, do you wanna save the changes?”
WARD:
[Chuckles] Right, we said, “Hey, we can’t solve the problem so we're not going to ask you, but we'll make it so it's not painful if you made a bad decision and left.”
CRAIG:
Right. And just to be clear, this is all with ngRoute, right? And in which version of the framework?
WARD:
No.
JOHN:
UI Router or ngRouter. It's both the routers that exist in Angular today.
CRAIG:
Okay. And you were like 1.2 of the framework or 1.1 probably…
JOHN:
It was 1.2. We don't know if it's changed 1.3. The new router will address some of these things though. The one that Rob wrote and I think Brian Ford?
WARD:
Yeah, Brian Ford worked on it. And they’ve made it asynchronous throughout. They’ve made it promise-based throughout. And that is so big -- the fact that the routers are now promise-based -is so big, and so I was curious about what Ember is going to do or has in the way of a page life cycle. I mean, the nested stuff, you know, that is a huge improvement of the UI Router over the ngRoute. The ability to define multiple views for a particular state, that's fantastic. I think that there is a clear win there, but this asynchronous page lifecycle control stuff, that's been missing over here and I wonder whether Ember has it. And I'm kind of curious, Craig, that whether you felt this urgent need that John and I apparently have.
CRAIG:
I haven’t, but honestly, I haven’t had that specific requirement, although it seems like a very reasonable one that almost everyone would have. I just haven’t run into that specific issue, but I do get what you're saying and that seems really real. From the Ember side, I'm fairly certain they do have something like this but it's sort of easy… we're kind of in the weeds here in a very specific use case, so I don't wanna say “absolutely,” but I'm fairly certain, you know, they’re kind of big on the lifecycle thing – let’s put it that way – in a lot of their objects, right?
JOHN:
Well, I think a lot of frameworks have had lifecycles, you know? .NET, Java, all these different frameworks had these cycles these frameworks for years. And what I like about what the Durandal lifecycle and in the new Angular one is there's like convention that you can follow. So you just name a function activate or can deactivate inside of your controller, those things just get invoked at the right time or right place. And then they have promises hooked into them so you can tell it to do things. And once you start using that, you start realizing how much code you no longer have to write to make those things happen. And I think that's the beauty of it and that’s why I'm really excited about where they are heading with it.
CRAIG:
Yeah, and I think that's the point. I mean if you want a backing of “why is this important?” You could say, well, Angular has obviously found it important enough to build into the newer versions of the framework. This is clearly an evolution, maybe you don't need these features in this specific app you're building but probably eventually you're going to be happy that you're using something that allows you this kind of flexibility.
WARD:
Craig, they talk about “state” in the UI Router. What does the “state object” mean to you within that context? Does it have any particular value as opposed to a route, right? In other words, the UI Router talks about a state object, then you talk to a state object. Whereas an ng-router, you talk about route. Is that just a difference in terminology or do you think there's substance there?
CRAIG:
You know, it does map pretty cleanly across, but one nuance that is not obviously is think about what if you wanted to change all the routes in your app? Like you decided that you didn’t like your routing structure? The way that the state provider API works if you look at it closely, the URL is just a property -- a configuration property -- and everywhere else in your app, you refer to your routes as states sort of by this state name that you give it. So at any point, you could totally like redo your URL structure. Don't ask me how much value that has, but it can in certain circumstances.
So it's kind of like this argument with the old in the data access days where you could totally switch out your SQL server backend for your Oracle backend, you know. When it happens, you're really glad there’s that abstraction there. Probably doesn’t happen that often, but I think that’s one major argument for having that abstraction is that basically, you're using these names everywhere in your application instead of using the actual URLs which has value, I believe.
WARD:
I agree. I feel that too.
CRAIG:
The flip side of that coin is you know, the abstraction of a state provider… so just to elaborate a little bit, backtrack, the UI router has this state machine abstraction on top of routes. So instead of dealing with routes, you're dealing with states in your application. And the states basically that works for most use cases but when you need like catch all route, let’s say for like a 404 page or to redirect to the login page, there's still another object called the URL router provider that is needed to do redirects and to do all those catch all routes. So they basically still have this sort of lower level router concept, it's just that you build most of your app using the state provider.
CHUCK:
All right. I hate to do it, but we got to start wrapping up.
WARD:
Oh, too bad because I just…
[Laughter]
The other thing that drove me crazy was the whole “provide” thing. It wasn’t dynamic construction of routes. You had to do it all [inaudible]… [Overlapping talks]
JOHN:
But we figured out how to get around that too.
WARD:
Oh, you did, but it's totally like, “Why did I have to figure out how to get around that? Why are they so locked in when the app starts?” And that those are the routes forever and how...
JOHN:
That will be our cliffhanger for another episode. [Laughter]
WARD:
Exactly. Oh, well! Go head, Chuck. Get us back on track.
CHUCK:
I know. Sorry. All right, John, do you wanna start us off with the picks?
JOHN:
So my first picks, or actually three. It's like the year of the Angular events and right now, we got ngconf just around the corner. That’s going to be wicked awesome. And it's got the whole Angular Team keynoting and doing a bunch of great stuff. And then there's also two events that I've learned about recently: one of them is Angular U. It's in June out in San Francisco. Ward Bell’s neck of the woods, unfortunately. [Laughter]
JOHN:
So I imagine he's going to be there.
WARD:
Is that like Angular “You”? You! You! You!
JOHN:
[inaudible] conference for Angular. [Laughter]
JOHN:
And then the third one is I think 2-3 days ago, ng-vegas was announced as well by our own Joe Eames. So we've got quite a bit of a year coming along with Angular. And some people have been saying, it's on the [?]. I think there's a lot more coming.
CHUCK:
All right, Joe, do you wanna do some picks?
JOE:
I will definitely pick ng-vegas since I announced that I'm helping to organize it. I do wanna make something clear: ng-vegas is not ng-Conf. it's not a subsidiary of ng-conf, but a couple of friendly associations is pretty much it. So if anybody was confused about that, do not ask any questions to ng-conf about ng-vegas; they are separate, completely unrelated events. So I’d like to pick that. I also wanna pick the book The Way of Kings by Brandon Sanderson. I’ve been on the Brandon Sanderson kick for just a long time now. Just consuming and reading everything I possibly can. And then reading Way of Kings -- really enjoying it. But I’ve also found just his shorter novellas are super awesome. I've never been a fan of short stories. And they are longer than short stories 30ish pages around, but man, they are just so well-written. I never thought that I would enjoy something that short but I've enjoyed. He's written like 5-6 of them. I've enjoyed every one that I've read. So that will be my real pick is Brandon Sanderson’s novellas and Way of Kings.
CHUCK:
Awesome. Ward, do you have some picks for us?
WARD:
I do. First, I'll mention Craig’s little post on the AngularJS UI-Router and that’s sort of the background for the discussion we had today. And we'll put that link in the show notes. The other thing is I tripped over, Ira Glass. Do you know Ira Glass, This American Life?
CHUCK:
Great show.
WARD:
Great show! And there were a series of interviews with him about how sees storytelling and what they don't teach you in school about how to write. And so I'll put some links for that. It's really fascinating and I'm trying to incorporate it into how I present. We'll see what kind of disaster that brings. But it's really brilliant and unexpected. And of course it's delivered in his very easily receptive style. So I'm going to put that in there and have you all listen to Ira Glass.
CHUCK:
All right. I've got a couple of picks. These are all my stuff but, but they are stuff that I'm working on. First off, as I've said before, I’m doing a Kickstarter campaign. If you zoned out for that, it's at the beginning of the show but it's a great way to support the shows. And ultimately, the goal is to make it so I don't have to spend so much time consulting, and I can spend more time doing the podcast stuff.
The second pick that I have is devboxclub.com and right now, I'm collecting email address and talking to vendors of various things that are of interest into programmers -- anything from stuff you put on your desk to books and t-shirts and stuff like that. And the idea is that you get a box full of interesting stuff every month. And so it's a subscription service, but I'm working out details and I'm interested to see how many people are interested in it before I go and pull the trigger on it.
The last one that I'm going to pick, and this is again, Ruby related but I'm going to put it out there and then if people don't care about it, then don't click it but it's Ruby Remote Conf. So last week, we had JS Remote Conf and it was huge success. Everybody seemed pretty happy with it. So if you're into Ruby, then go check out RubyRemoteConf.com. Craig, do you have some picks for us?
CRAIG:
I do, despite earlier on the call when we first hooked up, I was complaining about the amount of snow I have here in Columbus, Ohio but last week, I was at Disney World in Orlando. One thing I have found that was sort of surprising, I'd been there several times the Magic Kingdom, and there is a scavenger hunt that a lot of people don't know about A Pirate’s Adventure in the Pirates of the Caribbean area that’s totally free. And it's really quite elaborate. My kids absolutely loved it. We went there two days at Magic Kingdom. We didn’t have as much time to ride the second day and it was a very big surprise at how much fun it was and how elaborate it was.
Another pick is Sean Fioritto, who’s another self-published author. He does an Angular course, but he wrote this… calls it The Ginormous Unstoppable Angular Resource List of Angular Resources. And I give away like a resource list for each of the frameworks as part of my book and this has a lot of the same stuff I have on there, except it's absolutely free. It's out there, so I wanted to make people aware of that. I think it's a great exhaustive list of Angular resources -- one of the better ones I've seen. Those are my picks.
CHUCK:
All right, Joe, you have an announcement for us about ng-conf?
JOE:
Sure! At ng-conf on Friday, that would be the 6th of March. We will be recording a live podcast episode for Adventures in Angular. That will happen at about 12 o'clock, Mountain Time, give or take a few minutes. It will be live streamed, so if you wanna tune in at that moment and watch, you can actually see all of our faces in action!
WARD:
Oh, my!
CHUCK:
They are going to unshackle us, drag us out of the jungle and let you all see us.
JOE:
[Chuckles] Yeah, I don't know if that’s a selling point. I really don't.
WARD:
[Laughs]
JOE:
But we will be live. We will be unedited. You get to hear all of the “ums” and all of the horrible names we call each other that get edited out from the regular shows. You get to see it all. The first fighting, it will be there.
WARD:
Oh, excellent.
JOE:
And we'll be talking about ng-conf and our impressions, which is why we're doing it on day two to have as much of the conference behind us. And that will be the episode on Friday 6th. So you can watch it live and of course, it will be posted to the regular list of podcast’s audio-only later on. But you can watch it live and it will also be posted on YouTube shortly after.
WARD:
That will be the “Fifty Shades of Joe” episode, right?
[Laughter]
JOE:
Oh, let’s please steer clear of that. [Laughter]
JOE:
That’s something we're going to have to have edited out. [Laughter]
JOE:
You will be able to see live what normally gets edited out. [Laughter]
JOHN:
I don't know if we want to see anything associated with that, Joe. Sorry. [Laughter]
WARD:
Oh, but I have the vision! I have Joe in leather. It's just scaring me.
JOE:
Oh man. Ward, you're killing me!
WARD:
[Laughs]
JOHN:
Yeah, and this is from a man like Ward who knows a lot about wearing leather.
WARD:
[Laughs]
JOE:
I'm going to bring everybody one of those masquerade masks and we’ll do it.
JOHN:
Isn’t that Eyes Wide Shut?
JOE:
I don't know…
WARD:
[Laughs]
[Overlapping talks]
JOHN:
Chuck, pull the plug!
CHUCK:
I just got back from throwing up. I think we need to end [inaudible]...
[Laughter]
CHUCK:
All right, thanks for coming, Craig.
CRAIG:
Yeah, it was great to be on and talk to you, guys. Thanks for having me!
CHUCK:
We'll catch everybody next week!
[This episode is sponsored by Mad Glory. You’ve been building software for a long time and sometimes it gets a little overwhelming; work piles up, hiring sucks, and it's hard to get projects out the door. Check out Mad Glory. They are a small shop with experience shipping big products. They're smart, dedicated, will augment your team, and work as hard as you do. Find them online at madglory.com or on Twitter at @madglory.]
[Hosting and bandwidth provided by The Blue Box Group. Check them out at bluebox.net]
[Bandwidth for this segment is provided by Cache Fly, the world’s fastest CDN. Deliver your content fast with Cache Fly. Visit cachefly.com to learn more.]
[Do you wanna have conversations with the Adventures in Angular crew and their guests? Do you wanna support the show? Now you can. Go to adventuresinangular.com/forum and sign up today!]