Sessions is temporarily moving to YouTube, check out all our new videos here.

The Art of Mastering Ember

Laura Lebovic speaking at Ember London in March, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

5 key strengths to mastering Ember.js


Five recipes to master Ember that I have put together for the past year and a half. For those who are in the back, you can follow my slides on and So you can just visit that online. I've been building application for eight years before starting learning Ember. And at that time, I was working on the API and the UI using the same framework, on the rails. But I found myself quite limited using Ember, using sorry, previous framework. Using Ruby on rails for the UI. And I was spending a lot of time trying to make things happen. So I wanted to experiment with the new imaging frame in frameworks. And in my new job, it happens to be react. No I'm joking, Ember I picked up my first ever Ember ticket a year and a half ago in October 2015. So bear with me if this talk is not for you, but is more intermediate talk. It was about building a link with a, but as you might guess, things get more complex after. So I started gathering my thoughts on Mastering Ember, because I wanted to ensure that I got different diamond talks to push my skills to the next step. So a bit about myself. I'm Laura. I live in Dalston, London. East London. You can find me on Twitter, it's @lauralebovic, and don't hesitate to pin me or direct message me if you have any thoughts about that talk. My handle on getup is rubycalling. Obviously because I was a Ruby on I was born outside London. In a small town, two hours and a half ride by train. It's called Paris. And when I'm not coding, you can find me probably being busy boxing. And you can as well find me in some nice, summery festival. In France. And I love travelling. I spent some time exploring Asia and I lived in China for awhile. Now I'm looking forward to explore the far West. And I'm really happy to be planning my next trip, which will be in Portland, and where I will be giving that talk. So this is why again you're really welcome. I work at Show My Homework. We are building aapplication to help teachers create quality homework and provide meaningful learning experience for students. One in three school in the U.K. are already using our software. That is mainly based on Ruby and Ember. So now let's have a look to my cookbook. So I will be speaking about the art of mastering Ember. The five key strengths. And without further ado, let's jump straight into the first recipe which is organising your own routes. You will probably be finding some of similarity So let's go straight into that. So for me organising your own route is probably one of the most important recipes and what we are gonna do is we're gonna build an application where people can share their recipes online. So I hope that you guys love cooking. And what we wanna do is we wanna have this platform where people show their recipes. And when you actually click on one of the recipes, you can have this pop up. Where you can have the list of ingredients. So how we gonna build this pop up? Here could be a way to do that. Simply having an authenticated folder. Because we want our user to be authenticated to access. This part of the website. And we have the recipes folder that contains the recipes. And probably to have this pop up it will be a component named the ingredients model. And here's our template. In our template, we have a basic qo with the recipes list. And each li will be clickable. And when the user will click it, it will trigger an action that will be view ingredients. And it will send this action along with the recipe. So this action will to go a computer property, which is show ingredients. And the show ingredients, if it's true, then it will show our pop up. In our controller, as you might guess, we have a computic property ingredients, that will recompute every time we select a new recipe. And you will written the ingredient for that recipe. Simple, right? And then we have the view ingredient, as I told you that will set the selected recipe and will Finally, in our component, we can close this pop up. So we will to go again a property, show ingredients. Then we really, really want to forward this ingredient list to our mother, right? But what will happen then? So do you guys see all the problem? The problem is if we want to forward this, then we'll probably forward the recipe or the recipes list, but the computing property will not be activated. So even though you actually have it displayed on the screen, it will not be displayed for the guys or girl you wanna forward it to. How we wanna do that? We wanna have a And thiswill be the ingredients. By doing that, you can actually target ingredients, even though they are displayed in a pop up. And this pop up will be always, always activated when you actually send that link. So let's have a closer look. In the ingredients you have, again, rock controllers, good, and template. In the template, now it's getting a bit more simple. It's not an action we are having the li it item. But it's a link. And this link is purely a link to the ingredients route. And we passing the recipe item. Then in the component, as I write in the template, we have our ingredient pop ups where we actually write the model and the pop up. This is good, right? But we can do better. We can master it. Why? Because the problem is, if you think about it, we've run this model in the middle of our html marker. So what does that mean? It means that we might of the issue, and one of this issue might be css issue. Because what if the wrapper is limitating our model to be displayed absolute on the page? And I mean that for example, is the recipes list or the container has a position relative, then if the model adds a position absolute, it will have to be always looking where it is displayed. So why not make our life simpler? And render this model at the top of the route or at the very bottom of our application template? So what we could do, we can master it as I said, and we can look a bit more into details to the template. And we have this application the hbs template. That's it into the templates folder. So basically it's like our main layout. And we want to display our model in there. But without struggling with that, we have a nice hook, which is run the template. And this run the template will do all these jobs for us. We just have to say in which template we want to inject that model into. And give this outlet a name. So here we say that we want to render into application, and the outlet will be named model. And there we are. In application hbs we have the main outlet. And then we have our model. At the very, very, very end of application. And you will be free to be as thorough as we want. And it does not have to be placed according to its relative parent. And then we actually using liquid outlet with liquid fire to have a nice animation. So every time the model pop up, we could have a nice transition. Great. Are you ready for the number two recipe? Yeah? So the number two is very important as well. As you might guess, it's the importance of integration tests. So here we go. Our recipes website is growing. We have more and more recipes and we want to have a page with our main recipes, the home page and we want to have another page with the desserts. People can eat sweet corns as desserts. You probably might guess, for this two lists of recipes, the only thing that changes is the collection of recipes we pass. And we can use the component. So here in the recipes index template, we have the recipes list and the recipe entry will be a component. And we use that as well in the dessert template recipe entry, and the recipe is a dessert. So it's cool, right? The easy way to tell that is we want to test the flow, so we wanna say that, sorry, let's first have a look to the component. Component is pretty simple. You display foothold, you display the title, you display the header, and the date and the rating, and Miguel come by here will explain you a bit more about contextual components, so you might learn how to study better. But for now let's stick with that. So we have this component. And this is our test. This is a test of the recipes. It's our index, and what we are doing in here, we are testing the flow. Meaning I am visiting the recipes, and please could you tell me how many recipes are rendered? Okay it's fine, we have five recipes rendered. And then we say why not testing what is in the recipes? So the recipe title, the description, and the rating as well, picture. But if we have a look at the dessert, it's pretty much the same, right? So you are writing to acceptance test, where you actually have to build the app in the background and run the acceptance. And you are testing two flows. But we don't like duplication, don't we? So why not make it simpler and stick to testing the flow? Meaning visiting this URL and testing the behaviour of our component in the components test. So when we hear now, we have removed all the unnecessary component-related tests, and we are just getting the flow. So here we are testing only the qo and how many recipes are displayed on the page. Same for dessert. And here is our nice component test. So what is really nice with that you cannot have a lot, lot, lot of assertion, and it's not as expensive as doing that into an acceptance test. Because again, you don't have to test flows, you don't have to have a wall app for any of that. So yeah, easier, simpler, and less expensive. You master it. And I always say, at work, that every good test should tell a story. And this is really what we wanna do, is integration tests. And it's kind of your documentation actually. So here we know that the recipe for the URL is rendered, the title is rendered, , date, and rating. So it's really component-related and it's outside any contacts, so it can be displayed in the desserts, and it can be displayed on your home page. Now are you ready for the third recipe? Mock your ideal payload. So some of you might know, being, that sometimes our back end friends, dealing with them is not always easy. By mocking your ideal payload, we gonna tackle this issue. This issue is we settle with something that is not perfect, settled by the back end, because the feedback loop with the back end is sometimes annoying. If your team is distributed in different time zone, it can lead to ... Hmm, it will do. And as a front end developer, you just make things work with what the back end not deliver to you. To be honest. So why not using all the tools that you have in Ember to mock your ideal payload? Here, I'm giving a simple example. We simply want to have pagination. So at the very bottom of the page, you can see one, two, three, four, and you can see arrow on the right to go to the next page. And we want to highlight the current page. Here's what the back end tried to send us. That's cool. They send us a collection of recipes, and they send us some metadata. So they send us a We have 126 recipes, they send us a limit, enough said. Because they probably themselves, have just limit and upset to query the database. But how we gonna do that, how we can highlight our current page? By doing a calculation on the UI. So first, I'm trying to understand the total pages. So I'm grabbing my total con, 126, and then divided by the limit, ten, and I get 13 pages. Then I wanna know which is my current page. So I'm doing a bit more complicated calculation. Which is total pages minus total cons minus offset and this divided by the limit. And hoo ha, I get page three. So yeah, it can work, but the back end can do that for us, right? So let's make it work, and let's reduce the feedback look with API. Easier for the back end to adapt - it's easier for the back end to adapt to the front end because they know how to deal with logic. And the less logic we have in our template are in our control if, the better it taste for us, right? And when that included directly the calculated results into our payload. No, our response. So here we go. We have now the total pages, 25. And the page number, three. So with that, I can have my nicely highlighted page number. So it's fine, it's good, but you can master it, using JSON API. So basically by using JSON API, you can have even more information. So we still have our metadata, total pages, and page number. But we can have this information for email. At the bottom of the page, you have this arrow on the right, but the only way to know when to display it and when not to display it, and when to make it active or not, is to have these links. Self, first, prep, next, last, so the back end is just really helping us, and we don't have to care about a calculation again. And we master it. With just an API. Are you ready for the fourth recipe? Focus on the user experience. So our reader, after a certain point, they want to delete the recipe, because they want to make better one, right? And there's a pop up when they want to delete the recipe. But everyone is sometimes playing with the back button. And to delete recipe, and when they click on back the pop up is still showing up. Or actually we have a four four. Because no model is actually able to be fetched. So to be honest, in most case, we don't really care about it, and we don't really think about it. So how to make it work? And how again to make the user experience better? We can, for example, have this huge case where when we delete, we have a sole delete, and have the e deleted true flag. And when the user click on the back button, we don't him to say anything, because basically, it's deleted, right? So what we could do, is simply, checking if the model is deleted, and then if it's true, then the user will be automatically directed with transition to authenticated. So this will just be a quick transition and he will never see this pop up again. So this is good, this is nice, but we could do better. We can master it. What we could do, is when the user delete the record, we can even prevent him from when he click the back button to see this page again. That would be magic, right? And the way to do that, is to replace the last word in their history. In this brother history. And you do that with doing delete article. You're passing the article, you destroy your record, and then in theof the promise, you say that you replaced this route with authenticated recipes. The user will be brought back to the recipes and this pop up deletes route, will be removed in their history. So you master it. And I have another example that sometimes is really annoying. For example, we have the search field, and we wanna search for a recipe. And they don't really know how to search, and probably your grandmother is searching as well, and even youris not slow enough to mimic your grandmother typing for chocolate mousse recipe, right? So she will type ch, choc, hmm. But at some point she will want to go back to this recipes list, and she will click the back button. So it's pretty annoying, right? Because she will have to get back to all this flux, and it's not want she wants to go back to this main page. The nice trick is, to use again, replace. And you can say, new correct, search, you can refresh the model with a search, and you can simply say, replace truth and your grandmother is happy. And you master it. The last key, expect the unexpected. Four four, you know that one right? The Ember framework is really cool for one thing as well. Is that you can have specific error page, but sometimes again, we don't care about it, we have a generic error page. And we use catch-all. And we have a basic not found page. But this is fine, this is better than nothing, at least the user knows that something is going wrong, and you probably even have the four But it just really a static page, right? So why not make it dynamic? Dynamic. So again, this a generic error page. And this is our template. So let's master it. What we could do is with Ember, if you have next an error folder, into the folder where you might unexpect an error, and you can have a rot that will receive your error as a model. And by doing that, you can set up the controller, you receive the controller and you receive the model error. And then you can do whatever you wanna do with that. So basically you can build a really dynamic page that will tell more to the user about what is happening. So for example in here, we are grabbing the error and setting that to bugsnag. So at least the developers know more about that as well. And in the set up control you can even set some values, and here we are setting the error message that we will display in the template. So here we have this template that is now sitting under error recipes, and this actually give us more, more, more information entities. More user-friendly as well. Why, because we say that what it is the error page. And might have as well a link to go back to authenticated or authenticated route. So basically we gonna have something really specific for each main part of your website. So whether you are talking about recipes or whether you are talking about the form or something. So we master it. What we've seen today, we've seen how to organise your own routes, the importance of integration tests, how to mock your ideal payload and to be friends again with your back end friends, how to focus on the user experience, and how to expect the unexpected. Voila! So what's next? You can be a master. How could you guys be a master? You can get involved in the community. Because this is how I've learned what I've learned and how I'm now sharing with you guys. So you can meet other Emeberinos via Github, Slack, Ember meetups, they will probably help you with a lot of stuff. And what you have to know as well, is a lot of open source project are broken so if you find something that doesn't work you can probably help. Here is Sam Miguel at a project night at Show My Homework, and we were explaining lazy engines. And you can be a master as well by reading the official documentation. Read the rfc and comment on them. Even if you are a beginner, your voice will already be important. And therefore you can keeping up with the change in the framework. And lastly, you can create an addon and share it. The worst thing that will happen, really, is that you are the only one to use it. Thank you.