Using AngularJS to build a Portal with Brian Woodward| Episode 5

Brian Woodward - AngularJS ExpertOn this episode Brian Woodward describes his experience building his first application with AngularJS.  This is front-end developer cast episode 5.

Today’s interview is with Brian Woodward and was recorded a half a year ago now and focuses on his early experiences with AngularJS and is very valuable.  He also mentions his open source project Assemble which is a static site generator for Grunt.js, Yeomnan and Node.js that has rapidly gained a following in the last half year so you should also go check it out.  Here’s the interview.

To subscribe to the podcast, please use the links below:

Click Here to Subscribe via iTunes
Click Here to Subscribe via RSS (non-iTunes feed)

Show Notes:

Resources

Assemble (static site generator)
Brian Woodward on twitter: @doowb

Full Transcript

[0:00] On this episode Brian Woodward describes his experience building his first application with AngularJS. This is Front-End Developer Cast Episode 5.

[0:08] [background music]

Craig McKeachie: [0:18] Welcome to the Front-End Developer Cast, the podcast that helps developers be awesome at building ambitious web applications whether you're JavaScript ninja or you're just getting started. I am your host Craig McKeachie.

[0:30] Hi, everyone welcome to the fifth episode of podcast. I want to start by apologizing for not putting out at podcast for so long. What happened was I wasn't making the progress, I wanted onto my book, the "JavaScript Framework" guide, so I decided to focus on it for a few months, finish it and then get back to a more regular podcasting schedule.

[0:46] The good news is it worked and I finished the book. It's about 270 pages and five hours of screencast and video interviews. So, if you haven't already, go to javascriptframeworkguide.com and get your free sample chapter.

[1:00] The full title of the book is "JavaScript Framework Guide | AngularJS, Backbone, Ember, Confidently Choosing and Quickly Learning)." If you're interested in these JavaScript frameworks but haven't been able to keep up with the rapid pace of change, the book will help you quickly get up to speed with the whole bunch of the frameworks. I like to say, "You can read one book instead of five books." That's javascriptframeworkguide.com.

[1:23] I'm planning on doing a lot more podcast episodes in the coming months now that the book is finished, and I've got some great guest signed up. If you haven't subscribed to the podcast, please do so by going to the iTunes store on your phone or desktop, then searching for Front-End or via RSS by going to frontendcast.com We are also available on Stitcher.

[1:42] If you have already subscribed, then please take the time to leave a review on iTunes. This is the best way for people to find out about the show. Today's interview is with Brian Woodward and was recorded a half a year ago now and focuses on his early experiences with AngularJS and is very valuable.

[1:57] He also mentions his open source project Assemble at Assemble.io, which is a static site generator for Grunt.js, Yeomnan and Node.js that has rapidly gained a following in the last half year so you should also go and check it out. Here's the interview.

Craig: [2:15] Hi, Brian. Thanks for joining me today.

Brian Woodward: [2:17] Hi. Thanks for having me.

Craig: [2:18] Tell us a little bit about yourself, a little bit about your background before we get started.

Brian: [2:21] I've been doing .NET development mostly for about 10 years. I recently left doing enterprise work to create a start-up called Cellside. My last year, I've been focusing a lot on open source software. I'm one of the main developers on a project called Assemble, which is a Node.js build tool basically.

Craig: [2:43] The reason why I asked you to be on the podcast was I'm looking for people, some real world experience with some of the java scripts, MVC, MV* framework, the single page app stuff. It seemed like you had some good experience with the AngularJS.

[2:56] Can you tell us a little bit more about that project? Just maybe describe what the app did to start there and dig in deeper?

Brian: [3:03] The main goal of the app was to create a portal-type website for some of the clients that we had to expose some documents to them that they usually couldn't get to or that they had to call in and get to.

[3:16] The application itself was built, the front end was AngularJS and the back end was ASP.net MVC. We used the web API to connect to the front end.

Craig: [3:28] Tell me more. It's housing documents like a sharepoint type thing or like a smaller sharepoint or folder, structure, and stuff built into it. Tell me more about the interfacing, what it looked like.

Brian: [3:40] In the previous solution, some documents that have been stored on sharepoint, but people would have to call into the company and sharepoint was only exposed internally. Other documents were just emails that would get sent out sometimes as memos or just PDF files, things like that that weren't really stored anywhere.

[3:59] They were still sent to the customers or the clients. We just decided that we wanted to have a central place, a sharepoint was considered, but I think at the time there was security issues with it. Not security issues. It might have been licensing or just being it would have exposed it outside of our network.

[4:18] We didn't want to do that. Then we opted to be able to create a different front end so we could have our own security mechanism.

Craig: [4:23] That helps give me an appreciation for it. Do you remember which version of AngularJS you used for the project? Roughly, I mean.

Brian: [4:30] I think it was 1.02. Something similar to that. It was before they released the animation directives. I remember that part.

Craig: [4:41] How long ago did you start work on that application? Give me an idea of the timeline like how long you worked on it. That sort of thing.

Brian: [4:47] This application started, I think about six months ago. It would have been about July 2013.

Craig: [4:54] Worked like three months, six months on it?

Brian: [4:56] Yeah, it was a few months. We had it in test pretty quickly. There was another application that was built that we used some of the same infrastructure pieces that was a knockout-based application. It helped us by reusing some of the server side code.

[5:10] We were able to just put a new front end on with Angular instead of knockout.

Craig: [5:15] How big was the team you were working on when you were working with Angular? Just you working most of the time or was there a couple other people or?

Brian: [5:21] The actual team might have had four or five people on it. Two of us were dedicated to it. Two other people kind of floated around on it but they didn't spend too much time working on it.

Craig: [5:32] Did you guys specialize service-side versus client-side stuff or did you do a little bit of both each and that sort of thing?

Brian: [5:38] A little bit of both. The database stuff was mostly on me and one other guy that wasn't dedicated on it. That's why he's coming in to do some of the database parts, which was SQL Server database.

Craig: [5:50] Can you talk about what are the dependencies and libraries you worked with on the project like jQuery, jQuery UI or whatever you might have to include with Bootstrap, that sort of thing? Any of that stuff that might...?

Brian: [6:02] For the CSS, we started with Bootstrap. Then that was highly customized for our own look and feel. We customized it directly through CSS. We didn't use the raw less files or anything like that and [indecipherable 00:06:15] . We use jQuery in a few places but not for much.

[6:19] We try to use the UI Bootstrap project from any UI team and to try to get that working, but most of the controls that we had were just basic Angular directives. We didn't need to pull in a lot of special functionality.

[6:35] The one that we used mostly was the calendar control, which is an actual Bootstrap version that is a jQuery UI wrapped calendar. That one took some time to figure out and get working but it looked a lot nicer. It saved us a lot of dead time.

Craig: [6:52] What about testing? Angular has a great testing story. They do a lot of testing. Some people though don't quite get to the testing because it's a lot to learn the new framework, deadlines and so forth. How did it go for you?

Brian: [7:07] We didn't have any UI test. Any of the E2E test that they have, we actually didn't do any of those mainly -- it's a bad excuse, but it was the time frame that we're working in the server side.

Craig: [7:21] Just to clarify for the listeners the E2E...

Brian: [7:22] Oh, end-to-end testing.

Craig: [7:23] It's sort of a functional test what you would normally use Selenium or something like that, but Angular has a built-in test runner for those end-to-end tests.

[7:33] I think it's based on Jasmine style testing but I think they've changed it up a little bit and have their own type of binding so you can natively just run Angular controller or something like that, get the dependency injection that they provide on a regular app.

Craig: [7:50] Not many E2E test but lots of unit tests. Is that what you're saying?

Brian: [7:56] We had unit test on the server side for most of our stuff that we're doing. We didn't have a lot of business logic in the client-side of the app. We didn't really get in a lot of unit test because it was mostly just point data and displaying data. There was not much to...

[8:12] [crosstalk]

Craig: [8:12] A lot of business logic stayed up in the server actually. Talk to me about the process he used for choosing AngularJS over the other frameworks. You mentioned having done some work with Knockout on the project before.

[8:25] Some work could have been done with Knockout. Tell me what kinds of things you read, looked at and what made you set on and go to JS?

Brian: [8:31] There was a previous project that we used Knockout on. I like the way that Knockout does observables and bindings in that way. There wasn't a great way to do views, that was just a basic Knockout thing. Knockout was for binding.

[8:51] We looked at Backbone. I like Backbone for getting data from the server and everything like that, but I didn't like the way they did binding or their view things. I know that there's a Backbone.Marionette project, which I tried out and used.

[9:08] It made a lot easier for view management doing single page apps. I still didn't like how there's so much code that was involved for setting up basic bindings. Angular seemed to solve a lot of those problems for us because we could use the HTTP service, which is pretty much just jQuery.ajax wrapper and to be able to get to our rest end points and pool data in.

[9:32] Then we could just take a plain old JavaScript object and stick it into the AngularJS scope. Then everything was just watched for observables. You didn't have to declare anything. You had the entire deep object being able to be watched.

Craig: [9:49] In the app, were people uploading documents as well as viewing them in list as well as on an individual detail? Can you describe that a little more now that we're deep into this?

Brian: [10:02] The app actually had two sides to it. The front-end that we kept calling it was the client-facing on the Internet side of it and that part they could only view and download documents. The admin side of it was on our internal Internet. On that we could upload documents. Some of the issues that we ran into was uploading through Angular to the MBC back end.

[10:26] Initially, I tried doing it with asynchronous web API calls for, .NET. But we found out that the asynch calls run under a different app pool identity, or they run under the actual app pool identity instead of the intended user that we wanted to run under, so we were having a ton of permission issues.

[10:45] We found out that it was all to do with multi-threading. I wasn't very good with that stuff. I was like, "I'm not doing any of this asynch stuff," and we finally got the uploading to work. We had to use another component, too, which I think was a jQuery-based UI component that had a Angular wrapper.

[11:03] That was another one of those directives that helped save a lot of development time by going out and finding something instead of trying to build something yourself.

Craig: [11:12] I definitely had some challenges building directives that wrapped controls myself, but it sounds like you found one that did what you needed it to out of the box and so forth.

Brian: [11:21] Yeah. One of our biggest issues was we had to support Internet Explorer 8. A lot of the frameworks out there for uploading documents through Ajax did HTML 5. You didn't have that available to you. The other ones fell back onto Flash and things like that. I think that's the one that we picked, falls back to Flash, to the uploads.

Craig: [11:45] Maybe we can throw the link to that component in the show notes or something like that.

Brian: [11:48] Yeah.

Craig: [11:49] I think that would be useful for people, probably save them looking all around. [laughs] One thing I wanted to touch back on was you mentioned Knockout didn't really do the views. Can you elaborate on your thinking around that? I know that has a really good data binding story but what was your concern with the views there?

Brian: [12:07] I guess what I meant to say was mostly routing. Angular binds to the views that are HTML fine. In some cases, some of the issues that I did have though were when you tried to do nested type of binding scenarios. If you wanted to have one controller over a larger page, then you had to have another controller internally, or underneath, a child, I guess, of it. But your binding would complain sometimes, or things wouldn't bind properly.

But then the routing, I didn't find a good solution for being able to swap views out, to be able to give it a single page app type view.

Craig: [12:47] That makes sense. How did it go during development? What did you like the most about working with AngularJS? Talk about that first.

Brian: [12:55] One of the things that we focused on was making sure that we had our code separated out of our views because with ASP.NET, it's really easy to just put all of your JavaScript into the CS-HTML page. We made sure that we didn't do that, we used Angular's module system to try to build out small modules for the different services and the factories and our controllers and everything, to be able to pull those in.

[13:20] It just made everything feel clean and separated and easy to work on, especially with multiple people working on it. We could focus on one component of the site instead of everyone trying to put all the spaghetti code in the single file or something.

Craig: [13:38] That was one of the more enjoyable parts of it, was how organized you felt like the modular things got?

Brian: [13:42] Yeah.

Craig: [13:43] Did you use RequireJS or any of those new technologies for the modularity or were you just kind of managing it yourself?

Brian: [13:49] We did not use RequireJS. We used Angular's module system, which they have internally, which sometimes isn't as good as RequireJS. However, for pushing everything up and making sure that everything was available on the page we used ASP.NET's bundling API.

[14:08] That was a lot easier to do by just pointing at a little [indecipherable 00:14:11] string for the controllers or the directors or whatever we had. Then they would just bundle up and we could just toggle the switch for production mode and they were modified and bundled.

Craig: [14:23] What were some of the tough things, confusing and problematic things, that you ran into with AngularJS?

Brian: [14:28] The biggest issue we had, again, was in Internet Explorer 8, using Angular with Bootstrap, because one of the regular Bootstrap controls is for drop-down menus and the way that it requires it to work is by putting the empty href tag in there to get your menu to drop down. With Angular routing, it was causing issues and causing Angular to go into a loop. One of my co-workers got his Internet Explorer instance up to about 2 gigs of memory usage, just because it had that hole in it.

[15:02] But we were able to solve that, though, by finding a workaround by just in your anchor tag you can just put a "target equals self" and that just makes the problem go away. That was for Internet Explorer 8.

Craig: [15:13] When you mentioned about the challenges you were having with the menu and having to put the "target equals self" on that, can you elaborate a little bit more on that, clarify it for the listeners?

Brian: [15:21] Yeah, In Bootstrap, to define a navigation menu you use a UL, an Unalert List with the list items. You can create different sections in there at the different LI levels using hrefs tags. The hrefs don't link anywhere. They just have a hash-tag marker and Twitter's Bootstrap picks that up and is able to use the CSS to be able to create your drop-down menu and do the actions that it needs to do.

[15:53] But Angular also uses that same convention to do its routing. When you hit the hash-tag, it tries to find the root route and redirect you there. But in Angular, if you do a "target equals self" on an href tag, Angular won't pick that up and won't compile it. When we did this, that was our solution. That was what we found and that's how we figured out how to solve it so we didn't have the issue and we could still use the Bootstrap menu.

[16:21] However, after that, I found out about UI router, which is another project by the AngularUI team. I think that if I would have plugged that in, it might have solved our problem without us having to do the workaround. But I never got a chance to do it because we just finished the code and shipped it that way. We weren't trying to put in a whole new routing system after we already had the project done.

Craig: [16:44] Right. I think that will be helpful to our listeners. That's like a little gotcha hanging out there to know about. What do you wish you would have known about AngularJS or read more about before you started the project?

[16:56] Is there a part where you felt like you never knew it enough or you wished, that something kind of snuck up on you and gotcha that you weren't expecting?

Brian: [17:03] Like I said the first time was that UI router. I wish I would have known a little bit more because our hierarchy for our routes were similar to what it wants to do instead of the basic every single page has its own URL type thing.

[17:20] The other thing is I think is how to get interaction with jQuery, because there are so many people familiar with jQuery and how you can do DOM manipulation with it, where Angular kind of frowns upon doing DOM manipulation in your controllers and all that and would rather have you write directives to be able to do that.

[17:40] It's not that big of a deal, but there are so many tools out there that jQuery has already built around that do your DOM changes or whatever, you just have to wrap them, pretty much. That's why it's good to find these other projects, like UI Bootstrap or whatever. I think there is a jQuery UI one, too.

Craig: [18:00] That's helpful. Let's talk about architecture for a little bit. You mentioned on the server side you were using .NET and Web API. You kind of answered that bit of the question, so talk about syncing your model to the server and how you guys architected that with your solution.

Brian: [18:19] When you mentioned syncing, I always think about Backbone and how sync works and how it seems like it's automatic because it basically, just any time you update your model on the client side it goes back.

[18:30] Where Angular doesn't do that by default, so actually in this app, we didn't have any issues with having to poll to get data or anything, so we basically just, whenever you loaded up a page, we would go and pull the data from our Web API service and display the data there and then based on the user actions when we would send it back through to the back-end.

[18:54] To be able to make this easier for us, we built a generic service that just wraps the HTTP AngularJS service and we would be able to just pass in our route that we were going to take and our data and then optionally give it a type, like a POST or GET or PUT or whatever, based on our security concerns, because this was for a financial company and we had a lot of auditing and things like that. Most of our default was POST, even when we were pulling data we would POST to the server to get the data back instead of doing a GET.

[19:28] We wrapped it that way and then the generic HTTP service was wrapped in, I call them domain specific services, so for users, or for documents, memos, things like that, each one of them had their own Angular service and that way we could specify the routes for getting and putting or posting without having to specify those routes in our controller, so if the routes changed, then we could just change them in one place.

[19:57] Then all the controllers used those domain specific services to be able to get whatever list of data that we needed to be able to show on the screen.

[20:08] Then all the post or whatever were based on user action. In this app, we didn't do any kind of automatic syncing. In another app that we built that wasn't architected as nicely, we wrapped a lot of things with Angular's watch function to be able to detect if there are changes and based on some of the changes do polling and things like that to try get data to automatically sync up and change the UI for the user to notify, or something like that.

Craig: [20:37] That just wasn't needed in this app? Or, you felt like you had finer grained control with the approach you on this that you described?

Brian: [20:45] We didn't need it, because we were fine with the users having to either refresh a page or move to another page to view the data. There wasn't anything that changed frequently on the server side that we had to keep an eye on.

Craig: [20:58] You talked about the database being SQL Server and Web API. Did you use Entity framework or LINQ to SQL or anything like that, or did you do custom ADO .NET code. How did you wire that side?

Brian: [21:10] The company that had this art database was a very large database on SQL Server and we built a lot of small apps on top of it, mostly internal, this was only, I think, the second or third external facing app. We used our frameworks that we had already, so we had some custom built, mostly wrapped around ADO.NET type of data pool stuff, but that would get the information and then we used Web API to expose it.

[21:37] On the client facing part of it, the external Internet part, that Web API was exposed to another server that was outside of the firewall, so we had custom authentication that was passing through that way, using the web client and Web API 4 or MVC 4.

[21:57] Then the people using the front end of the site, we had just a regular membership provider type ASP.NET membership provider set up and created their passwords and user names and all that, just like a regular website that wasn't using the Windows Security to do. Just regular forms security.

Craig: [22:17] Forms authentication, role stuff. Backbone apps tend to be a lot about the model and there's a lot in the framework about the model, whereas Angular focuses more on the declarative UI, the data-binding and the good testing story, and so forth, but they can't pride themselves on the plain old JavaScript objects. Did you find yourself sort of missing the kinds of things in that are in Backbone, like events, or the ability to extend from a base object, that sort of thing? You mentioned a lot of the business logic was on the server, so maybe that wasn't an issue.

Brian: [22:50] Some of the patterns that we followed, we created some regular JavaScript files that weren't in an Angular module at all, and we put them into our known namespace on the window in the browser so that way if we were going to create a new memo object, we could just pull that from our namespace. Do it like a new app.models.memo, and then be able to pass in some stuff, or whatever, and we'd get our default structure so then that way we weren't sure we were passing that back to the REST service properly.

[23:24] We didn't do any base class or anything like that to wrap anything or to inherit from, which usually you do with Backbone to get your listeners or events or things like that. I think Angular does have an eventing system, like an event emitter type thing that you can use. We didn't take advantage of that at all. Looking back, I probably would if we were doing more on the server side for setting notifications up to be able to say "A new document's ready for you to view" or something like that, but we never really had the need for that.

Craig: [24:02] Just curious to dig into this a little bit more. You had your factories or your services that were returning entities. Did you say services before or did you guys use factories?

Brian: [indecipherable 00:24:13] [24:13] staff for me. To me it's all the same. Factories, service or provider. Provider? We didn't use the providers at all because we didn't really have configurations that were different. That could have been something that would have been interesting to do, going back on it, because then we could have set up our URLs for the REST services that way. But I think we used either service or factory.

Craig: [24:38] There's such a slight difference. Give me an example of what a service or factory would look like and what kind of methods were on it, and what it returned, and that sort of thing.

Brian: [24:47] We usually had the basic CRUD methods on there, so we had a get and a save, or sometimes we had an additional methods for getting a list of information or a getting a single item. We had a lot of drop-down menus for different things that we call service's. Since those had to be used on almost every page to show whatever service you were looking at or to be able to select the service, that's why we build the services to be able to get that list for any page that we were on.

[25:19] The service also allowed us to cache if we needed to. You load up the page. Since it's a single page app, your JavaScript code is all there already. You basically have a fat client on the browser. The first call, we would pull the list of services and those wouldn't change often.

[25:37] The service would take care of caching that information on the browser just by storing it into a list and then the next call to that function would just return the previous list that was brought up. We reduced our network calls that way.

Craig: [25:50] Was there a mapping between what the object coming back from the RESTful service looked like to your client side model and was that done inside the service?

Brian: [26:01] Most of our mapping, we had models on the server side in C# and the Web API does a good job of mapping all the stuff to a JSON object. We basically just took advantage of that. We didn't really do anything else for that. Except, we also would create objects wherever we had to create a new object in JavaScript. That's when we basically create a schema, I guess you would say, just a skeleton of what the object would look like so that we'd ensure that we would have the same column names or property names and everything like that.

Craig: [26:39] Except for on the creation of a new object name on the client, you really didn't have a mapping between what the server was sending back in terms of JSON and the client object model because it was just clean enough that you could use it as is...

Brian: [26:52] We mostly handled everything in C# for that. I can see another pattern where you're doing different types of translations on objects or creating additional properties and things like that, it would be nice to pass a plain old object into a constructor for a JavaScript object and then you can get additional properties on that and pass that to Angular into the scope, but we didn't have a case for that.

Craig: [27:19] Would you say your app was, this is going back more of a navigation thing or URL thing. There's a lot of conversation around, "Should an app be a strictly single page app and never reload", or "Should there be islands of functionality or silos of functionality." How did you guys end up with your applications?

Brian: [27:37] On our admin side, it was a single page app completely. There is one main controller that returns an index view that just had the ng-view tag and that was it for our admin part. We had a template controller that would return any other CH.HTML pages, then this way we could use still use Razor syntax to do some findings on the server side if we needed to. That was a true single-page app.

[28:04] On the client side, just because we wanted to take a little finer grained advantage of the request token, I'm blanking on the full name of it. It's the anti-forgery request token. We want to do that, so all of our account management type pages, log-in, log-out, password change type stuff, were all their own page, so it was rendered from the server and then brought up and then posted back to the server. Then the internal part of it was all single-paged app, other than that.

Craig: [28:41] Do you touch a little on the deployment process and build tools and maybe talk about what IDE did you use, Visual Studio for most of the development or did you have a text editor. Talk about how that worked for you on the project.

Brian: [28:54] We used all Visual Studio 2012. We never got into 2013 at the time, which I think has new tools that I haven't checked out yet for doing a lot of JavaScript stuff. We did all Visual Studio on our deployments because it was an enterprise and we already had the infrastructure for our other stuff. We used TFS and we'd check-in there and then there's a build server that builds everything. We would have different config files, web config so we could specify if it was a dev or production environment to be able to do the bundling and minification properly.

[29:29] For the front end stuff that's really all that was different in the different environments was the bundling.

Craig: [29:35] This was really helpful. I think the listeners will get a lot from this and from your experience with Angular and I really appreciate you being on the show today.

Brian: [29:44] Thanks for having me on here. I like talking about this stuff. Any time I can find someone.

Craig: [29:50] Thanks.

[29:52] [background music]

Craig: [29:55] Thanks for listening to the Front-End Developer Podcast. Please subscribe to the podcast by going to the iTunes store on your phone or desktop, then searching for "front end" or via RSS by going to frontendcast.com where you'll also find show notes and a full transcript of each episode. If you're interested in my book I mentioned earlier, go to javascriptframeworkguide.com and check it out. Thanks. We'll see you next time.

Trackbacks/Pingbacks

  1. Dew Drop – July 29, 2014 (#1824) | Morning Dew - July 29, 2014

    […] Front End Developer Cast Episode 005 – Using AngularJS to build a Portal with Brian Woodward (Craig McKeachie) […]

Leave a Reply