Lesson 6

Components

37

⚠️ This tutorial uses an old version of Ember. Some things might have changed!

Components are a way to break up your website into small, reusable parts. If you've worked with React.js or Angular.js before, you're probably already familiar with this concept.


Generally, you will find that components offer a much more practical way to organize the front-end structure of your web app, compared to the traditional MVC-approach. One of its coolest features is that it more or less lets you define your own HTML-tags, which can be much more descriptive than having just another span or div-tag.

Preparing the home page

Let's take a look at the mockup we have for our home page and see how we could "componentize" it:


Splitting our page into these 4 components seems to make sense!


Keep in mind that Ember embraces the W3C Web Components specification, which says that web components must have a dash in their name (this is so that they don't collide with existing or future standard HTML-tags). Therefore, the name of our components will be:

  1. profile-glance: shows a summary of the user's profile. Clicking on it takes you to the profile page.

  2. status-update: clicking on it opens up a modal where you can compose a new chirp.

  3. chirps-list: a list of chirps.

  4. chirp-message: a single chirp. Notice that this one is inside of chirps-list (components within components are no problem!)

Our first component

Let's create our first component! Bring up the terminal and type:

You'll notice that Ember created two different files for the component: template.hbs and component.js (as well as a test-file). One is for the markup, and the other for the JavaScript logic. Let's add some markup in the Handlebars-file (we're still just using static data for now):

app/components/profile-glance/template.hbs

That will do for now. But how do we make the component show up on the home page? It's actually as easy as dropping the custom tag {{profile-glance}} directly into the home-template! We'll also put some layout tags around it so that it shows up exactly where we want it:

app/home/template.hbs


What you should see now.


It works! Although it doesn't really look that great, so let's style it with some CSS.

Scoped CSS for your components

Now, we could go to our styles-folder, create a new SCSS-file there and then import it into app.scss just like we did with the other stylesheets. But since we're using components, I want to show you something even cooler!


Erik Bryn, who is an Ember Core Team member, has written a nifty Ember add-on called ember-component-css that let's you specify CSS directly inside of our component's pod folder. This prevents you from having to repeat your already existing folder structure in the styles-folder, plus, it solves many of the problems that arise with the fact that CSS uses a global namespace. So let's use this library!

Now, in our profile-glance-folder, we can simply create a file called styles.scss and all the the styling rules we specify will be scoped to that component only!

app/components/profile-glance/styles.scss

In order to make all your component stylesheets part of Ember's build process, you simply need to add this line at the very end of your app/styles/app.scss-file:

After you do this, the app will crash, so restart the Ember server (so that the new add-on can be detected) and refresh your browser to see the results:


Hello there sexy component!


It's starting to look good! Although there's one final touch. By default, an ember component is actually a div-tag containing all the elements that we specify in the component's .hbs-file. How can we add a card-class to this div-tag so that it gets styled like a card?


For this, we have to go into the component.js-file, and specify the desired classNames as an array:

app/components/profile-glance/component.js


The final result!


That was it! In the rest of this lesson, we'll go through the same process for the rest of the components.


Since you know the drill now, we'll only show the generating code that you need to run in the terminal and then the contents of the files, without any elaborate explanation. Also, remember that we're still just using static data in our files, there's no actual behaviour in our components... yet!

The "status-update"-component

app/components/status-update/template.hbs
app/components/status-update/styles.scss
app/home/template.hbs


The result


The "chirps-list"-component

We will fill this template with a list of chirps soon, but for now, let's just show a default "empty" message.

app/components/chirps-list/template.hbs
app/components/chirps-list/component
app/components/chirps-list/styles.scss
app/home/template.hbs


The result.


The "chirp-message"-component

The chirp-message component is a nested component that always lives inside of chirps-list, so here we specify that we want the folder structure to be nested as well:

app/components/chirps-list/chirp-message/template.hbs
app/components/chirps-list/chirp-message/component.js
app/components/chirps-list/chirp-message/styles.scss
app/components/chirps-list/template.hbs


The result!


Good work! We're now done creating the static version of the "home" screen, and you should have a pretty good understanding of how to split up your designs into Ember Components!


In the next chapter, we're going to take the first steps towards making this data dynamic by using Ember Data.

Comments

profile/avatar/default
HarlocK

White background-color missing? <br style="color: rgb(77, 83, 81);"><br style="color: rgb(77, 83, 81);">& {<div style="color: rgb(77, 83, 81);"> margin: 2px;


<div style="color: rgb(77, 83, 81);"> background-color: white;


<div style="color: rgb(77, 83, 81);">}

profile/avatar/default
Foreverneilyoung

Definitely. And there is a green background in the status update...

Ben Kolera

On the 2015-08-15, ember-component-css 0.1.5 was busted. Downgrading to 0.1.4 fixed things. Details: https://github.com/ebryn/ember-component-css/issues/85

Tristan Edwards

@matwb: This seems to be the problem: https://github.com/ebryn/ember-component-css/issues/121. Could you try upgrading your Ember CLI version to 2.4.1?

profile/avatar/default
Włodek

Thanks. Upgrading ember-cli to 2.4.1 fixes this.vendorStaticStyles.concat is not a function

profile/avatar/default
Foreverneilyoung

On my machine this looks different. How can I add a screenshot to this comment?

Tristan Edwards

@foreverneilyoung: You can upload an image somewhere (http://imgur.com for example) and link it in the comments. :)

profile/avatar/default
Włodek

After restart the server crashed with: $ ember server


version: 2.4.0


this.vendorStaticStyles.concat is not a function


TypeError: this.vendorStaticStyles.concat is not a function. Any idea how to fix this?

Visva DevWorks

For this simple (not responsive) but very nice design, you may add:


border-radius: 3px 3px 0 0;


to .cover-photo tag. Having this, the entire container is beatifully rounded, as the others are. :-)

profile/avatar/default
Włodek

Is this intentional: $ scss-lint styles.scss


styles.scss:1 [W] UnnecessaryParentReference: Unnecessary parent selector (&amp;)

Mh Mh

CLI isn't creating separate component folders for me. I have an app/components folder with component.js files, and an app/templates/components folder with my component hbs files. Have I missed a step?

Mh Mh

I think I've found a fix for this: a --pod flag. So it would look like: ember g component profile-glance --pod

Tristan Edwards

@mhmh: Are you sure you updated the .ember-cli file with "usePods": true in this chapter? https://www.ludu.co/course/ember/templating That should suffice. :-/

Mh Mh

Ah, you are right--I did that but somehow didn't save the change. Thanks!

Guillaume Barthe

I encounter a problem with broccoli that tells me app\styles\app.scss is not found despite I have created it. Stuck with this issue.

profile/avatar/default
Jerimy

Really I just had to say thanks so much Tristan... I was on the verge of giving up on my ember project because the 2.0 documentation is so poor IMO. This course along with 2 other links I found today helped the lightbulb come on for me, and I have finally stopped tripping over deprecation roadblocks... This course is more than worth the 30 bucks and I will be sending others here to learn what I have ;)

Tristan Edwards

@jerimy: Thanks Jerimy, it means a lot! I'll make sure the course is updated! :)

Daniel Jeffery

Ditto here, I might not have persevered with Ember if not for this course - I think it needs a sequel to be honest!

Manvendra Singh

Could you please tell me where is that 'profile-glance' class?

Manvendra Singh

I can see there are two classes 'profile-glance' and 'profile-glance-c3f1da25'.

Tristan Edwards

@manvendrasingh: Exactly, the wrapping div gets the profile-glance-class. profile-glance-c3f1da25 is added automatically by the ember-component-css library (so that it can scope your CSS).

Manvendra Singh

Thanks! But where is then 'profile-glance'? I can't find it in any scss file. :-|

Tristan Edwards

@manvendrasingh: It's in app/styles/profile.scss :)

Kirk Israel

wait, app/styles/profile.scss ??

Adam Marinelli

Found the card class in app/styles/ui.scss

Manvendra Singh

Thanks @tristan. Now I found where that profile-glance is coming over. I figured it out and then later read it in addon's docs. This class is used for namespacing rules in styles.scss file. Thanks for the info Tristan. :-)

Adam Marinelli

Ah, @kirkisrael, I see your previous comment about this.

Visva DevWorks

Small typo: the file name is component.js.

profile/avatar/default
Louie Solomon

In case anyone is wondering, the "tagName: 'ul'" line changes the component from a div tag to a ul tag. see: https://guides.emberjs.com/v1.10.0/components/customizing-a-components-element/

Andy Pickler

Small typo: "...an ember component is actually ***a*** div -tag..."

Tristan Edwards

@andypickler: Thanks! Fixed it.

Kirk Israel

Should you mention that .card was previous declared in ui.scss ? In case people didn't notice when they copy and pasted

Michael Bernal

just a heads up, it appears you removed the h1 "home" tag, but did not mention it. if one is not copying/pasting the code, this could be missed

profile/avatar/default
Louie Solomon

@michaelbernal Thanks for pointing this out. I was having alignment issues because of that.

profile/avatar/default
Foreverneilyoung

That looks insane in Chrome

Carlos Eduardo Papacidero

I had to restart ember every time that Ive create a new component style?When i ve created this new one, the css changes only appears after a restart.