cult3

Understanding and Creating Components in Ember

Jun 08, 2015

Table of contents:

  1. What is a Component?
  2. Why would you use a Component?
  3. Creating a Component in Ember
  4. Generating the Component
  5. The Component Template
  6. Passing data to Components
  7. Customising a Component
  8. Adding interactivity with actions
  9. Conclusion

As Web Developers, we work with the building blocks of HTML to create websites. HTML is a standards-based markup language that provides the foundations of how pages are rendered in a web browser.

Web Components have been have been talked about widely for a number of years now.

Web Components are essentially a way to extend the HTML specification to create elements that better serve the requirements of modern websites and applications.

This allows you to create encapsulated and reusable nuggets of code that can be used as a first class element in HTML.

There are currently many different initiatives to make the dream of Web Components a reality, and there are a number of people working on this problem.

Ember has created it’s own Web Components implementation that is trying to stay close to the W3C proposed standards.

In today’s tutorial we will be looking at creating Components in Ember.

What is a Component?

Before we get into creating a Component, first its important to understand Components and the benefits they bring.

A Component is an encapsulated and reusable nugget of code that extends the HTML standard.

This means you can create your own HTML tags to describe a certain element of your application.

This tag would know how to render itself into the useful component. This would include it’s CSS and Javascript for style and interactivity.

The Component is encapsulated and so it is protected from the outside world. This means that CSS and Javascript can’t leak in or out.

When you break things down into Components, you can compose your application from this reusable chunks.

For example, imagine you have a user profile widget. Instead of repeating this code to place this widget in the sidebar, in the footer and in the main content area, you could just reuse the same Component.

Components can also be made and shared as part of the Open Source community. For example, something like a Google Maps Component, or a latest tweets Component would be really useful for a lot of websites or applications.

Why would you use a Component?

So hopefully my quick overview above has given you a better understanding of what a Component is, but you still might not be convinced that this is such a good idea.

Components solve the problem of duplication and lack of encapsulation in front-end web development.

If this is not your first time at the web development rodeo, you’ve probably encountered the situation where a certain aspect of your website or web application needs to be used in multiple places.

If you’ve unintentionally coupled that “component” to it’s ancestor CSS or Javascript it can be difficult to pick it up and have it appear in a totally different area of your website.

Or perhaps you have encapsulated your “component” correctly, but the outside evils of where it is situated are creeping in and messing up your work.

Components solve this problem by creating a fully encapsulated element that can be placed anywhere and easily reused. The CSS and Javascript is written specifically for that single element and so you aren’t coupled to the outside world.

By creating Web Components we can extend the HTML standard to create complex and interactive User Interfaces without getting into a mess of bloated HTML, competing CSS or slippery Javascript.

Creating a Component in Ember

So to show you how Ember Components work, I will be creating a simple User Profile Card that you will often see on social websites like Twitter. This will display the user’s details and profile picture. The markup for this card might look something like this:

<div class="card">
  <img
    class="card-profile-picture"
    src="https://randomuser.me/api/portraits/thumb/lego/1.jpg"
  />
  <div class="card-actions">
    <button class="follow-button">Follow</button>
  </div>
  <div class="card-content">
    <h3>Philip Brown</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
  </div>
</div>

Generating the Component

As we’ve seen a couple of times over the past couple of weeks, we can use Ember’s generators to create the boilerplate infrastructure we need for a Component:

ember g component profile-card

This will create the following two files:

app/components/profile-card.js
app/templates/components/profile-card.hbs

An important thing to note when creating a new Component is, every component should have a dash in it’s name. This is yet another convention of Ember, but also an important one to ensure that there are not naming collisions with future HTML element names.

The Component Template

First we can move the HTML from above into profile-card.js file under templates/components:

Now we can use the following tag to display the Component:

{
  {
    profile - card;
  }
}

If you create a new index.hbs file, add the tag above and then fire up ember serve you should see the component rendered to the screen!

So that’s great, everything is working, but to be honest what we’ve done so far isn’t particularly useful. You could achieve the same result by simply using a partial.

Passing data to Components

The first thing we need to do with this component is change it so we can pass data to it. This will make this component reusable for every user of the application:

<div class="card">
  <img class="card-profile-picture" src="{{avatar}}" />
  <div class="card-actions">
    <button class="follow-button">Follow</button>
  </div>
  <div class="card-content">
    <h3>{{name}}</h3>
    <p>{{bio}}</p>
  </div>
</div>

Now when we use the tag we need to pass data for each of the template placeholders:

{{profile-card name="Philip Brown" avatar="https://randomuser.me/api/portraits/thumb/lego/1.jpg" bio="hello world"}}

In a real situation you’re probably going to be passing data from your backend to the Component, you can kinda see this in action if you stub the data in the Route:

export default Ember.Route.extend({
  model: function () {
    return {
      name: "Philip Brown",
      avatar: "https://randomuser.me/api/portraits/thumb/lego/1.jpg",
      bio: "hello world",
    };
  },
});

You can then update the Component tag to be:

{{profile-card name=name avatar=avatar bio=bio}}

We looked at passing data from the Route in Working with Routes in Ember.

Customising a Component

When we used the generator command to create the Component earlier, you may have noticed that two files were created.

The profile-card.js file under the app/components directory allows you to customise your component:

import Ember from "ember";

export default Ember.Component.extend({});

For example, by default your component will be rendered as a div element. To change this you can set the tagName property:

export default Ember.Component.extend({
  tagName: "aside",
});

There are various other things you can customise when creating Ember Components, but we will look at them in more depth when we come to creating our own in future tutorials.

Adding interactivity with actions

Finally, the last important thing to look at with Ember Components is adding interactivity. The whole big benefit of using a framework like Ember is making interactive websites!

To add interactivity to your Component, you can simply use the {{action}} tag we saw in Using Templates in Ember.

However, instead of bubbling up to the Controller, any {{action}} tags will bubble up to the Ember.Component we looked at in the last section.

<div class="card">
    <img class="card-profile-picture" src="{{avatar}}" />
    <div class="card-actions">
        <button class="follow-button" {{action "follow"}}>Follow</button>
    </div>
    <div class="card-content">
        <h3>{{name}}</h3>
        <p>{{bio}}</p>
    </div>
</div>

You can then deal with the action in the Component:

export default Ember.Component.extend({
  actions: {
    follow: function () {
      //
    },
  },
});

Conclusion

Web Components are an excellent idea that seems to be just on the horizon of becoming a reality. There are a number of initiatives and a lot of clever people getting behind this problem, and so native web components are probably not that far away.

Ember is pushing forward to adopting these new standards and conventions as a project. Ember’s implementation should also hopefully make any future movement towards standardised Web Components as easy as possible.

Therefore there’s no reason not to start using Web Components to better structure your projects today. In future tutorials we will be looking at how to better organise and take advantage of Components within an Ember application.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.