 They are Adil Aziz and Pranit Kapula. Adil is a front-end engineer at Bang the Table, same place that Jason Justice from yesterday works at. Jason works with you guys, right? And he has a special interest in UX UI design. He was fortunate enough to have his first computer at a very young age. Yeah, dude, very jealous, at all jealous. And you learn more and more about him by breaking it and fixing it. He's a free software evangelist and a strong supporter of them. Outside of that, he's a movie buff, music lover, and an aspiring writer. Pranit Kapula is a daily design thinker, weekend cook, and occasional photographer. After an engineering degree, he has dabbled in the design world, researching technology products for the underserved design interfaces and services. He has worked at both large organizations and startups. He's evangelized for UX and setting up UX teams. And he currently heads the UX team at Bang the Table. So the designer-developer combo of Pranit and Adil, they'd like to tell you about some experiences that they had by building and rebuilding an app with AngularJS. Guys, the floor is yours. OK, now. OK, awesome. Hello? Yeah. So yeah, we are here to share a story of the experience of building a complex web app entirely in AngularJS. Why AngularJS? How that happened in just a minute. But so first, a context to this complex web app that we talk about. Engagement HQ is one of our primary product offerings from Bang the Table. It's a platform for community engagement used by over 200 clients, primarily in the government sector in markets like Australia, New Zealand, and Canada. They use this platform, essentially, to share information, listen to the feedback from the local communities, and then learn from whatever they're hearing and implement that. So here's an example of Southeast Queensland water. It's a government body which manages all the lakes in Southeast Queensland. They've set up the site, essentially, to talk about the recreational reviews that they're doing in terms of what facilities that they can give to the local communities around, like picnic spots around the lakes. And people can go do horse riding next to the lakes or swimming and all these things. So they have all these big ideas, and they wanted feedback from the community in terms of how do they want to go about it. So just a bit about this. The structure is like, you have information about the project up there. It's like a long page. So down below over there would be the feedback tools. We have a new suite, quick poll, and some surveys running over there. And on the right are the widgets that support this information. So this is the platform in action. Now, imagine what this would be in a mobile browser. It's like a crappy zoom in and zoom out experience every time you have to go in and do something over this. And we did notice a spike in our user base in a span of 12 months. So somewhere around June 2012, we had like 10% of the end users accessing these sites across all the sites from mobile phones. And that started going up to about 20%. And that's when we said, we need to do something about our mobile experience for the end users. A bunch of us got into a room, started brainstorming. End of the day we came up with this paper prototypes. And then we were like, we had no clue in terms of how we are gonna do this, but this is our experience, vision of the experience of what we wanna provide. Little Adil in the corner of the office takes a look at it and says, oh, you need a app like experience on the browser. It needs to be responsive fast. I've been experimenting with Anglerges. Let me take a shot at it. He actually convinced us that he can actually build it all up alone. And we said, okay, great. Go ahead, man. And well, it did turn out well. And 26 days we had a, go back. Yeah, in 26 days we had, we demoed this at Seavit Australia. Yeah, we rebuilt it again. By 86 days we had the final launch. It actually went live a couple of weeks back. But yeah, how did this whole experience go about? So this is the graph that Ben Adil, a famous front-end engineer who blogs, went about mapping his emotions as he went about building the Anglerges app. So what he talks about as you start using it, it's like, oh, nice, that's so cool. And then the very next day, you're like, man, this is so lame. I should go back to my backbone or the usual stack that I have. And then, you know, ups and downs, mood swings and all. And we are no strangers to this. So let me stop here and ask, how many guys I've actually dabbled into Anglerges or used Anglerges in your, right? How many guys experienced this mood swings? Right, exactly. A few of you, and this is, we were also the same. And a little story over here, Adil one day at 11.30 in the morning, we have a usual team, Adil is nowhere to be seen. I call him up, he sounded so depressing, I thought, okay, well, he's having his Angler day. And, right, in the night, a bunch of us, we were locking up the office, we were stepping out, probably catch some dinner and then head home. We see Adil step out of an auto fresh as a daisy. You know, he's figured it out. He's gonna hack all night over in Anglerges now. So yeah, those were the kind of days that we had in these 86 days. So we'll go through some of the product requirements, how Anglerges helped us and what we went about it. So this is like a basic information architecture for our sites that our clients use. So essentially it's a website or in community engagement terms, a consultation hub, which has multiple projects running in it. Each which is called a consultation and each one of those will have these feedback tools and widgets and all. And sometimes even the consultation hub might have widgets and tools. So what we are talking about is essentially like nested views and the ability to conditionally change behavior of the template in the views. So Adil, how did we do this? Yeah, as Pranit said, we wanted to have parallel views and nested views. And in some cases we wanted to, excuse me, in order device? So yeah, now, good, yes. So what we wanted was, you know, conditionally change certain templates, let's say in seven you go to certain URL, you want the header to be different. Or you want in certain cases, the entire thing changes into something different layout. So we wanted all that. So first we, and in some cases we also wanted to attach certain data, particularly URL or route. So our first choice was to use dollar route, the default Angular service in, you know, Angular routing service in Angular code. And we tried it to have these parallel views and all, but it all started getting a little bit nasty because there is, you will have to be forced to rate a lot of conditions in your views. And even the Angular ways that you embrace using logic in views sometimes, but this was like getting too complex. And we started to look for alternatives and then we eventually stumbled upon Angular UI router. Angular UI is an independent project from Angular. So they have this libraries and all those stuff which will help with your Angular project. So this Angular UI router is basically a state-based routing framework. So what it will let you do is that it will let you organize the various parts of your interface into a state machine. So here in this state machine, a state is essentially a place or a place in your user interface in terms of overall, you know, navigations and various states that, or various states that a user could go to when it do some actions. Yeah, and you can also attach views and various behavior and optionally give it a URL. And when user go to that URL or when the state in that state machine get active in an implicit way when they go to the URL or when user take an action, what happens is that in this state, appends its templates and URL to their layout, right? So I think I will go back to the code and show you how we define this. So this is app.coffee. What it is, it would strap your Angular application. So here you can see the configuration file. Is it readable? So what you can see is the configuration function and you are essentially injecting state provider which is part of the Angular UI library and you are using the state method to create a state. So it takes two parameters. One is the state name and the other one is an object. Or this is how you write an object in CoffeeScript. So this object will have different properties attached to it. It has a URL here and it is resolving some data before loading that and it, I'm giving a string as the template here and I'm also attaching a control to that. So in this app.coffee what we have and we have a couple of other states as well. So what we are doing in using these root status is factor out all the commonalities in your page. So in most of the page, you will be having the same header and same footer, same navigation. So in using these parent status, I'm factoring out. It's just like work like a layout manager if you think in that terms, right? And in all these states folder, I have state definition for various tools. So if you see for the guest book, what I did is I gave the name as project.guestbook. So what happens is it becomes a parent of guestbook state and I'm also giving a URL to this and attaching certain data to it. And here if you can see, I am targeting to a parent state and attaching a template that and giving a controller. So here I used template URL and the athlete loading using you know, XHR, the file and it will give, you can ultimately use a string as well. And there's one more way which we'll get back to you. Yeah, so remember, I talked about the agility in our process, the ability to actually restart the entire thing. Anglers had a role to play over there, but essentially when we were looking at all the product requirements, we saw there were a lot of patterns that were repeating. The case in example being the comments. So most of our tools like news feeds, stories, forums, guestbook, all had comments and even a tool like Q&A where people ask questions and site admin can answer them. It was essentially submitting a comment and therefore you're getting it. So we were talking about you know, how could we use some of the reusability features of AngularJS and get things done much faster and Adil will show you a couple of ways of how you could achieve this. So what we as planners said, what we essentially want is to reuse the same controller views in various routes. So all these features will be having this comment function. Let's say question and answers have this. It's similar to comments. So you want to change certain stuff in some cases, right? So if you go to the survey or sorry, a forum, it may not be as exactly as this implementation guestbook. So you still want to change some part of this controller views, but you still want to reuse certain stuff. So how you do that? So we figured out it is basically generate, you want to generate dynamically some state objects which will use all these things. But one thing, one implementation thing we couldn't figure out at first was where will I put this state generator function? I want something which is injectable to configuration function. So what the solution we found is that we wrote a custom provider called state generators. But here in this case. What all does a project manager has to do, right? Yeah. So here in this case, we are only injecting this provider, this custom provider to the configuration function of your application, like app.config. But since we are not injecting this to any other parts, so any other controllers or any other services, we don't need dollar gate method to do anything here. And what this function do is that it takes all these parameters. What is the URL? What is the heading? And what data, what is the function which resolves all the data which, what is the placeholder and various state things so that we can change stuff depending on that. So I am charging some custom data here. I'm also resolving them data. And so remember I said how we can load templates in this state. So first you are using template property where you can just give a string. And the second way is using template URL. The third way is to essentially you get to a template provider. What it do is that it gives you a function which is injectable. So I'm injecting HTTP service and all those things. And depending on certain condition, I'm loading different views here. So I'm targeting to the project frame which is a layout for all these project views and in the head region, right? And in this head region I'm loading if the user is logged in or if their current user is present, I'm loading this view. In the other case I'm just loading the generic header. So that in some places you can get, you want a different header for that. Let's say for usability issues, you want to have a submit button on top of your fields, you can do this trick. So this is one way which helped us achieve and ensure usability in our code base. The other way which angler helped us to ensure usability is using the RTIVs which is very similar to web components which Chris has planned this morning. So I'll show you some examples before. So here in our home page we have this, this is basically a photo gallery widget. So we have little thumbnails index of all the photos present in the database. And you can swipe and drag and do all those things, right? And when you open this image, you still have that same interface component here which do the same stuff. So we are using the same thing in video gallery. We have the same pattern in video gallery for project home page and in individual shop page as well. So what we did is, I'll show you the photo shop page here. So here you can see that we have a custom HTML element which takes certain attributes and this will essentially give us that interface component. So how we do that? So we use darkties for that. So if we go back and look at, you know, gallery panel, darkt code, you can see I'm restricting this as an element. I have given a certain template for that. And here in this link function, I'm giving all the code which needed to do that, swipe effect and all those things. How you slide into it, what will happen when you click on that. So all these are given and I'm also isolating this from the rest of by overriding its scope. So I have this items type and which is a project which is associated with some API. So you need to know which project it is so that I can load it from API and all. And since video and photo index differs a little, I'm also getting the type as an attribute. So here, this essentially let us reuse the same thing as is as expressive as you, how you would write a P tag or H one. All I had to do everywhere I had to use this, I just write gallery panel and what is it? And I just pass in the photos, photos list, right? And actually we can, we actually we had a feature called QtPort which lets the users take a conduct QtPort and all. We build out the end there functionality using a narrative. So this is QtPort. So why we wanted to do this? So this QtPort can be either a widget or it can have its own page. So it is coming in multiple places. So, but I didn't want this to be interfaced with, I mean, yeah, this to interface with the rest of this thing. I still wanted to make this functional and have all those functionality around it. You know, ability to view results there, change words and all those things. And if you go to the, so if you go to the individual QtPort, QtPort see all page, there is multiple QtPort here. So if you select this, this should not be interfering with any of the rest of the components, right? Any rest of the QtPort. So we, what the best solution we found is to write a directive for that which will essentially have its own control. So this is the directive it takes as a, this is the template used for that. There is a scope which operates, which is the QtPort and what is the project it is in. And it has its own controller and we do all the stuff there itself. Let's say if you want to, the response code, how you post the response back to the server, how you, what will happen when you view the result. All I'm doing is I'm changing a variable here. So if I, the view show is result, angular ng if directive will display that part. And the powers of directive does not end there. So you can also, you know, right? I'm just restricting it as an element. You can also write your own custom attributes and custom classes using the RT. So I'll show you one application we did that. So in the sign up form, so this is basically the input field for user registering. So there we have the sign up form and it has this attribute called ng model. This is basically the RT which comes as part of the angular core. So any RT which is namespace with ng comes with angular core. So we can also name our RTs, ng but it is not a best practice to do that. So here I am attaching, I am binding the model value, model variable to this using this ng model attribute. And I'm using each unique login. So what I want to do there, as soon as a user under login screen name, where we sign up for a form, I want to check whether it is unique. I want to go back to the server and check whether a user named already in that name is exist or not. So there are a lot of custom validator. I mean, there are a lot of validators which come with angular, ng required, ng minimum, these few of that, but this is something which angular does not ship with. So what we did is we wrote a custom directive which takes ng model as a requirement and in the linking function of, in the link function of is unique directive, I am injecting the controller of ng model directive. So after going, checking with the API, whether the current user is unique or not, I am setting, using the setValidity, dollar setValidity method of ng model attribute. I mean, ng model directive to be true. So this unique validate, unique validate is true if and only if the response back from the server, if that particular user is unique, we'll set that as true. So here, I'm using the same directive for not just for login, but also for account email. So here, the same, same directive, but I just said this is the email we are checking if it is unique or not, right? So in cases, so in some cases, so this is all isolated from the rest. So in some cases, we may want to let other decoupled components know that something, if something happens, let's say we want to do some interface changes once this unique validation check is over, once this check is done in the server, right? So what we are doing is, we are broadcasting an event called unique check. We're along with the response we got from the server, whether it is unique or and other parameters we have. So usually events in Angular works in a scope level, but in this case, I'm broadcasting in root scope itself. So everything in the application will, we can inject root scope and then look into it, then do you think the dollar on method get that, you know, even notification then? So actually this particular part helped us in creating a very unique experience in our mobile sites. So if you are site advance, if they choose to have unverified user access, so as they are participating, not only registered users, but even browsing users want to participate, we would just want to get their email ID and still allow them to participate in a particular survey or anything like that. But how would you know when a registered user is actually trying to take a survey, would you actually pull them away from the survey, show a login page and then bring them back to the survey? We didn't want to break that experience in there in that way. So what we did was we essentially use this unique function broadcasted it and the user has a seamless experience throughout. He just enters his email. The server would say, this is not unique. We already have it. Give him the password field right there. Enter this password and from then on in that session, we have him as a registered user. So we don't really have to move between login screens and change his views. So what this that is, let us do is that essentially teach, this is something I found in Twitter. So this what this is essentially doing is that, extending the vocabulary of HTML. So as expressive as you write HTML, you can have to just use H1 tag or P tag, just like that you can write all these complex interface conferences. So again, going back to the complexity of the app itself. So within the same site, we had multiple different projects. I've shown you the basic information architecture. So there are different types of projects. There could be an open project, which is like any browsing user can get access to the information put up on a project. We could have a protected project, which is like only registered users get access to this project. Or we could have a panel project, which is like the admins decide who are the site of users in the community who get access to the information on this project. And all these projects could lie under the same site. So again, this was something that we had a block in terms of how do we go about this. So what we essentially want to do was, as soon as the client request for a resource, if this API refused to give that resource back, if they pair as bonded with the status code, like a red status code, let's say another store or protected, what we wanted to do, we want to let the client know what should do by then. So what we essentially want to do that, before giving the response from the server to the application code, we want to intercept that response and take action based on the status code. So what we have this concept of intercept is in Angular. What it essentially does do is that, so here I'll show you how the access control work here. So we have a factory method, which returns a method, which takes a promise object as argument. So the $http service in Angular, which is used to do all kind of adjax request or any kind of extra request or not, work based on this $q implementation in the Angular code, which is basically a promise deferred implementation. So what it do is, here I'm taking the argument as an a promise object, and if it is not successful, if I'm using the then method to change it, if the response was not successful, I'm checking if the status is either unauthorized or protected, or if it is not in the user login page, I am essentially redirecting the user to send in page if he's not logged in yet, or I'm just giving him a message, redirecting some other page and telling him this particular resource is restricted for him. So if we are doing checks in the UA as well to not show that link, but in cases if they use absolute URL to access something, this kind of checkiness. So writing a method that's not like is not enough, we have to let no $http service that this is an interceptor. So how do you do that? You in the, so coming back to the app.coffee, the application bootstrapping file, I'm injecting the $http provider and there is an array called response interceptors. So I'm essentially pushing the access control interceptor that interceptor into this array. So what it'll do is any response from server before getting the promise passed into the application code, it just runs this method first. And here I'm returning the promise object, but you don't have to essentially do that. In this case, we don't want to do any modification here. You can do modification to the promise object as well and return that as a promise object. All you have to do is you have to just return a promise object. So we can do all kind of error handling, any sort of complex set using these interceptors. It's very powerful. So yeah, today we didn't went into anything into detail, but we just touched upon these concepts. It helped us a lot to make this project a reality. And a lot more, which actually, Angular have this filters concept, which she's used for any kind of transformation or pre-processing of your data before displaying in your view. So one example I can name is, so before you display block of test, if there is a URL, you want it to be put inside an anchor tag so that user can click on that URL or email address. So we have a filters filter for that, which will essentially, you can use the Unix syntax, the piping syntax where you pass it through that filter and it will essentially take it and I find solve the URLs in that and just combine it with put it inside an anchor tag. We use DolorWatch for the dependent question feature of the survey tool, which is essentially if a user answered this question, then only show the other question. So we use the DolorWatch in Angular to do that. We use DolorEval for the customizable tool name. So we have all these customizable tool names in our application to display that as well as to map the mobile URL. Mobile URL is different from our desktop versions URL. So to map the mobile URL with all the arguments, parameters and not to the equivalent desktop interface so that switch to desktop link works all the time. Yeah, so do find us offstage and we're happy to share more code, show us example, show you guys examples and talk about more of the stuff. And we are very happy and thankful to these guys who've made their awesome open source projects. And finally, I'm Pranit, I had the UX at Bang the table and I'm Adil, I do front-end element at Bang the table. We would be happy to answer any questions. Just one thing before you start asking questions that the whole reboot in terms of how we built and rebuilt, it was only Adil who was doing all that stuff. So it was one resource throughout 86 days who got this app out into production. Okay, then... That's awesome. We are the, they've got it all or we just made a full stop. That's a win for you. That's okay. One other thing, we also want you guys to see the app that we built. So you could go to angulartalk.engagementhq.com. You could give us your feedback. There's a short survey, three-question survey. You could actually use the app and see how it works. And the other thing that we've been thinking through these few months is there's no local community for AngularJS and we wanted to see if there's any interest for such and we would be happy to host like a monthly event or maybe make a fair show and tell kind of a thing where people can bring in their projects and talk about it and share about those. So it's angulartalk.engagementhq.com. Okay, all right. I'll tweet it and we'll retweet it on the JS4 account. Everybody big round of applause for Pranit and Adil. Thank you. Thank you guys.