 of ambitious user experiences. So a bit of a disclaimer, this is my first ever talk. So if I say anything stupid, please feel free to send me an angry tweet. So some of you might notice I have a bit of a strange accent. That's because I grew up in Singapore and I moved to Australia six years ago for college and I've lived there ever since. I started out as a self-taught designer. My dad gave me a copy of Photoshop number 15 and after following a bunch of tutorials on the web, I fell in love with design and the web in general and I've been designing ever since. I also taught myself how to code and I currently work as a front-end developer at HONLY which is a real estate search engine in Australia and I've been working with Vimber for about close to two years and I love it a lot, which is why I'm here. So before I begin, I just want to give a quick mention to Dockyard, I promise Brian, I promise Brian I would put like a big ass logo, Dockyard. So here it is. For those of you that don't know Dockyard is a design-focused consultancy, they do lots of Ember awesome paperwork and re-hiring so if you want to work on some cool Ember projects or if you want to hire Dockyard to work on something cool that you're working on, speak to me later and I'll introduce you to the team. As I was saying, Ember makes it really easy to build ambitious user experiences and by ambitious I mean a user experience that leaves no questions unanswered. The web has evolved and it's a richer and more interactive place. It's no longer enough to just build a purely functional app, it needs to be designed well too. So in this talk I'm just going to go through a few easy things that will help us to build good user experiences in Ember. I'd like to start off by addressing very common misconception about design. A lot of developers think, I'm not a designer, design is boring. I'd rather work on real problems because they believe design is about how things look or feel or animate. But they're wrong because design isn't just how it looks or feels, it's about how it works. And as developers, we already make a lot of design decisions every day. We decided how to name variables, functions, classes. It's one of the hardest problems in computer science. We also decided on things like tab versus spaces, convention over configuration, API design. That's all part of the developer experience, which is really important for productivity and general developer happiness, which is why we all use Ember. At the same time, it's the small thoughtful decisions that define a beautiful user experience. That my comment gets posted, that this website itself is working. What just happened? These are just some of the questions that people will ask when they use your app. And if they don't get questions, sorry, if they don't get clear answers to those questions, then we fail these people. Now although it's called the user experience, it's people that use the things we make. And when no thought goes into design, you end up with something like this, with features all over the place. Pretty good UX, right? Now here's an interesting picture of some salt and pepper shakers. Can I get a quick show of hands? How many of you think the salt shaker is the one with one hole? And how many of you think the salt shaker is the one with many holes? See isn't this interesting that something so simple is we can't even decide on? It's pretty much half for those of you that can't see. But the answer is it doesn't matter what you think. What matters is what the person who filled them thinks. And that's what you have to consider today when you build apps. It doesn't matter that you think people can find it, install it, or use it. What's important is what people think. And designing for people is hard, especially on the web. Because unlike the physical world, people can only interact with your app through one or two senses, right? Sometimes sight and sometimes sound. So design is really important. And if you need a five minute tutorial to explain how your app works, that's really bad design. And I hope none of you are doing that. So what is good design? I think good design is a number of things. And here are a few of them. So firstly, I think good design is reactive. And by reactive, I mean instant feedback. Or in other words, the user is always aware of the effect of each interaction they make, as well as the state of the system at any time. And we do this through reactive programming. So to understand reactive programming, it's really simple. Just look at the spreadsheet. It's made of two cells, A1 and B1, where you can input a value. And C1 is kind of like a computed property, because it's just the value of A1 plus B1. And this value will update immediately if either A1 or B1 changes. And it will always maintain the relationship between those two dependent cells. So in other words, reactive programming is about the continuous flow of data and maintaining relationships between that data. If you were to do this in vanilla JavaScript, you'd have to explicitly listen to change events, then manually update C1 when a dependent value changes. And that's no fun, and it's only a really simple example. So Ember enables reactivity through the observer pattern. This is implemented with the observable mix-in on every Ember object. Functional reactive programming is reactive programming's functional cousin. In FRP, in addition to being reactive, it's also functional. Now, a pure functional language has no side effects, right? But in FRP, data is immutable, but we get to keep the behavior of side effects, but retain that functional style. So in FRP, interactions are expressed as event streams and properties. An event stream is like a series of discrete events, such as mouse clicks, keyboard inputs, touch events. And properties are similar to streams, except they also have a current value, which sounds familiar, right? So here's a property you're all probably very familiar with, I hope, the mouse. When you move your mouse, its position can be expressed in XY coordinates. And moving the mouse immediately updates the coordinates, and there's a clear representation between the physical position of your mouse and its digital representation on the screen. So every mouse movement is value over time expressed as a stream. If you imagine that stream to be an array of events, then you can use functional methods like map filter, reduce, and concat to transform these event streams and properties and make our UI more reactive. If you're interested in FRP, I highly recommend checking out Bacon, which is a fully-featured FRP library. But obviously, this is in BaconCon, this is EmberCon. So we're going to look at how Ember implements FRP, which is in the same way. So we're going to use a few key tools to build reactive UI. The observer pattern is a mechanism for FRP and Ember. We consume this pattern with computer properties and observers on any observable. Computer properties take one or more properties and reactively transforms them into some new value. When the dependence change, it updates and relationships are always kept in sync. Here's a simple example, one you've probably seen and used a million times. The full name, computer property, observes the first name and last name property on some object, and this returns a string that joins them together with the space. But as our app grows larger and more complex, we might find repetition in our computer properties. So in order to make our quote dry and testable, we can refactor this into a macro. Macros are basically functions that return a definition of a computer property or observer. There are a number of chips of some of these out of the box, but we're just going to take a look at how we can write out on really quickly. So let's just say joining together a bunch of properties is really common in our application, and we're doing this everywhere with a variable number of properties. So instead of repeating ourselves like 100 times, we can write a macro to abstract this, and this is how we do it. So first we're going to define a function that takes two arguments, a separator and an array of dependent keys. ComputeFunk is a computer function that maps those dependent key values into an array, and then we just join them together with a separator. But we can't return the string yet because it's not observing anything, so when the values change, it won't update. So we need to apply the property method on the computed property with the array of the dependent keys in order to observe all those dependent keys. And now this macro will work on any number of properties that you pass into it. So here's a quick demo to show you that bindings will still work when values change. I'm not actually going to show you the demo, but you can have a play of this later if you take a look at the slides. So as you can see, the macro is a lot better. We can reuse this on any number of properties throughout the app, and we can avoid repeating shared logic, and it's way easier to test. As I mentioned earlier, Embershift is quite a few of these out of the box, and have a look at the API documentation for more, and if you can't find something you want, it's really easy to write your own. So unlike computed properties, observers don't return values, that the observed changes on dependent properties and are synchronously invoked when dependent properties change. All of you probably use computed properties and observers at some point, so I won't go into too much detail. But now let's take a look at three simple things we can build in Emberhift to improve UX in general. So in addition to being reactive, I think good design is playful and has personality. Not sure how many of you have used Slack. I use it every day, it's one of my favorite apps. But those of you that don't know, Slack is like a team chat tool, kind of like IRC for teams. And one of the things I like best about Slack are its loading messages. It's really playful, it has lots of personality, and never fails to bring a smile to my face when I open up, yeah. Also how many readers do we have here? So one of my favorite subreddits is shower thoughts. For the two of you in the audience that don't know what reddit is, it's like kind of like a big firm. And on shower thoughts, people post philosophical thoughts to get in the shower. The link below is a video of Nick Offerman reading some of these shower thoughts. It's really funny, so just you have a look later. This very quickly gonna read to you some of my favorites. Waterboarding at Guantanamo Bay sounds super rad if you don't know what either of those things are. The person who would proofread Hitler's speeches was a grammar Nazi. And if your shirt isn't tucked into your pants, then your pants are tucked into your shirt. So anyway, I decided to make a slack loading message cone, but with random shower thoughts instead. It's a really easy place to start. It's really easy to implement, but it's also just a nice little thoughtful gesture you can add when you inevitably have to load something in your app. So in Ember, when we return a promise in a route, the router will pause the transition to resolve that promise. For example, if we're at the index and we wanna go to the user's route, if a loading route's defined, the router will equally transition until the promise fulfilled. And the router through the store will fetch the record from the API, which will return a promise. And if the promise resolved with the records, we transition into the user's route. If not, we reject and we transition into the error route if one's defined. So for our shower thoughts, loading messages clone that we're gonna build, we're first gonna build a service that fetches posts from the rated API. And then we're gonna build a simple loading message component that retrieves fetch messages. And whenever the route returns a slow promise in the model, the router will enter the loading route and display a shortcut. So first let's create the service. Gonna use a relatively new class called Ember service. This extends from Ember object and we can lazily inject this later using the new inject helper. We're gonna start off with some really basic properties. First of all, an empty array to hold the fetch messages in memory so we don't have to do multiple Ajax calls and just some other properties for dealing with Reddit. First we'll define a simple method for getting JSON from the rated API. This is just a simple Ajax call wrapped in a promise. And then when the service is created, the init hook is called. We will observe the subreddit and top period properties on the service so we can make this dynamic and we can change. When the service is created, we'll perform the Ajax ones and then we'll set the messages property to the fetch posts. So now in the component, using the inject service helper which has been stable since 110, you can lazily inject the service into this component. So the component can now access those fetch messages from the service and then we're gonna write a really simple computer property macro to randomly pick a message from the array. So this macro is really simple. Basically it just observes all the messages in that array and then just returns a random one with the computed property set to be volatile and read-only so that it won't be cached and we'll get a new message every time we enter the loading message route. So here's a quick demo. So as you can see, when you enter a new link message, you get a random share of thought and you can change the period. It's really simple but it's a really nice gesture for your users when you have to load something from the route. So I think good design is also informative and people wanna know what's going on at any time in the app. So one of Jacob Nielsen's ten heuristics for UI design is visibility of system status or in other words keeping the user informed about the state of system with appropriate and timely feedback. So the web is so rich and interactive nowadays. It's not just static Geocd sites anymore and it's become really important that this heuristic is fulfilled because we all know how frustrating it is when you go to a website and you get a blank screen or you click and nothing happens. It's really frustrating. So one way to keep users informed about what's going on in your app is flash messages or ground notifications kind of like how Rails does it. Basically we'll use this to inform users of what's going on during some interaction that they've made. So first again to plan what we're gonna build. It's again a service that we're gonna inject into controllers and routes. The service will contain a queue of messages and each message will be wrapped in a component so that the user can click on it to dismiss it. So again let's look at the service. This is basically how we want the API to look. We wanna be able to create messages from a controller or route with a really simple API and for convenience we're gonna add bootstrap style method names, success, warning, info, danger. We also wanna add custom message types and clear the messages on screen. So we'll start up again with an inverse service and some properties and then we'll hold the queue of messages in the array called the queue property and all created flash messages will get pushed into this queue and will be removed when the timeout elapses. For the public API, success, info, warning, and danger will carry the add to queue function with the type filled in as you'd expect. The use of ES 2015 syntax for default values when there's no timeout arguments. This is really awesome. As well as the add message function at the bottom for custom types. And then this one's really simple. We just get the queue and we clear it by sending it to an empty array. So for defining how the add to queue method will actually work, this simply creates a flash message object and then pushes that into the queue and then this function will create the new flash message object and then hold the reference to the service so that it can remove itself from the queue after the timeout. So far so good, this is really simple. Now we're gonna create an ember object that will represent the model for our flash message. The first six properties are gonna be convenience properties using ember computed macros. We're also gonna have a timer property to hold the reference to the destroy timer. So when an ember object is created and it's called and what this function will do is use the ember run loop to call this destroy message method after the timeout has elapsed. We're also gonna set the timer property on the flash message object to refer to that call so that we can cancel it if the user destroys the message before the timeout elapses. Otherwise we'll be trying to destroy a message that has already been destroyed and ember will hate you for that. The story message will simply remove the message from the queue and calls ember object destroy. This sets the is destroyed flag to true and once that's been set, you can no longer set any more properties on the object because ember doesn't like that. So now we can expose the destroy message method as public API. We can call this from the flash message component that we're gonna build later to destroy the message early. So the will destroy method is called when an ember object is about to be destroyed and then this override will simply canceling the timer in case it's already been destroyed. So now with the service and the flash message model we need to inject this into controllers and routes and in the future, routable components so that we can use the service. So again, we can use the inject helper or we can also use an initializer to inject the service across all controllers and routes. This is pretty straightforward so I won't go into too much detail on this injection and then the component is gonna be very simple as well. The template will just yield if the template has been passed into its block helper and if not, we'll just render the flash message. The component is really simple as well. This just binds to classes so we can style this into a strap and we'll add a click handler so if you click on the component the flash message will be deleted so the user won't be annoyed by a million flash messages appearing on screen. And now you can just render the flash messages really easily in your template. For example, in your application controller and you can also pass in a template block for a flash message if you wanna do some custom styling. So, again, another quick demo. So this is really useful, especially if you use Ember data, you can use, for example, if you're saving a model that returns a promise, you can hook into the .vin or .catch methods on that promise and you can return a flash message. So for example, if a model saves and it rejects, you can pop a flash message and say, hey, that didn't go so well. All right, so that's, it was really simple, right? It's like 30 lines of code, we'll take that. As a quick aside, you can install this as an Ember CLI add-on today. It's called Ember CLI Flash. Pull requests are welcome. And finally, good design is intuitive. People are going to interact with your app in a way that's intuitive to them. So drag and drop doesn't really work for all use cases but it can be a good interaction, especially if you're building an app like Trello or a Google Calendar. Drag and drop is really good for those use cases. And it turns out this is really easy to do in Ember. This is like 25 lines of code or less. So again, to plan our approach, we'll build a, sorry, again, to plan our approach, we're going to use the HTML5 drag and drop API. Unfortunately, this doesn't have the best mobile browser support but it works fine on modern desktop browsers and we can augment this later with a touch of that library. So what we're gonna do is to create a drag-on component where a draggable item component can be dropped into and then we want to be able to send an action from the drop zone to some controller or routeable component to handle the drop events. Thankfully, we don't have to set up drag and drop event listeners ourselves because Ember handles this right off the box inside of any Ember class that extends from EmberView which includes components. And as it turns out, making something draggable in HTML5 is super easy. All you need to do is add draggable to true, to any element and it becomes draggable. And as we're actually transferring data between the drop zone and the items that you drag into it, we can make use of the get data method on the event. So let's take a look at the drop zone component. The first thing we want to do is handle the draggleave, drag over and drop events, drag over and draggleave will simply set the classes on that component so we can visually signal to the user that this is actually a drop zone where you can put stuff into. And then in the drop handler, we'll use the get data method in order to retrieve the data from the item that was dropped into it. And then we'll call the component send action method to delegate it to something else like a controller or a route. And that was it. So simple. So now for the draggle item itself. As mentioned earlier, all we need to do is set draggable to true so that the browser makes this draggle. And then we'll listen to the drag side event so when the user starts dragging that component element who we can use the set data method to get the data from whatever content is in the template and then pass it into the drop zone. Because we want to keep this interaction as generic as possible, the template for both of these components is just gonna be you, which means we'll have to pass in some HTML into the block helper. So this is a really simple example. In this example template, let's say we have two dibs. One for all available users and one for all selected users for some chore like clean the toilet. So first, we're gonna set up the draggable drop zone component and then we'll bind the drop action to add user on some controller or route. And then we'll just iterate through those unfortunate users who have to clean the toilet by outputting their full name to a list. And then for each available user that is ready for that task, we wanna be able to drag their names across into the drop zone. And then we can just iterate through them and set the draggable item component content property to their user ID so we can retrieve this later from the controller. So now in the controller, we can add an action to handle the add user action that accepts a user ID as an argument. Let's say this controllers model is all of the available users. So we're gonna find the drop user from the model using its user ID and then we'll just push that user record into this selected users array. And that's it. So, as you can see, that was super simple. And in less than 50 lines of code, you have super simple drag and drop. So these people expect you to clean the toilet later. Just joking. All right, so to help refresh your memory, we looked at what design is and what it isn't. It's not just about how it looks or feels. It's also about how it works and sometimes that's more important. And we also looked at three really simple ideas that we can build very easily in Ember. Loading messages, flash messages, and drag and drop interactions. We looked at how good design is reactive and people wanna feel in control. Good design is playful. People feel delighted when apps show personality. Good design is also informative and people wanna know what's going on when they use your app. And finally, good design is intuitive and people are gonna interact with your app in a way that's intuitive to them. It's important that we build interactions that will let them do that. So in certainly, Ember makes it really easy to build ambitious user experiences and it's really fun too because Ember provides probably the best developer experience and this freezes to really think about the user experience of the apps that we create in Ember. So in closing, I'd like to ask you two really simple things. Remember design is not how it looks or works. Sorry, not how it looks and feels. It's how it works. And shameless plug, please follow me on Twitter to get notified when I write more about Ember posts. The slides are available at this URL, bit.ly slash sugar pirate. And I know you're all really hungry right now. So if you have anything to ask me or if you wanna get some information about Dockyard, please look for me during the snack break which is coming right up. And thank you for listening. Hope you enjoyed my talk. Thank you.