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.

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

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

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

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:

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

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 "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 "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

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.

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);">}

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

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

@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?

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

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

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

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? 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. :-) Is this intentional:$ scss-lint styles.scss

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

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?

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

@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. :-/

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

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.

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 ;)

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

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

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

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

@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).

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

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

wait, app/styles/profile.scss ??

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

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. :-)

Small typo: the file name is component.js.

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/

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

@andypickler: Thanks! Fixed it.

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

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

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

That looks insane in Chrome

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.