Components patterns in Ember.js

Maciej Kwaśniak
Dec 10, 2018 · 3 min read

As an Ember developer, you are probably familiar with components. Thanks to them you can split your code into meaningful parts. Unfortunately, it’s not always obvious how they should look like, and which pattern should you use. This snippet should let you better understand what kind of components patterns you can use to be the best match for your case.


Here are all the components patterns I found in the Ember community, that I think is good to know.

Components patterns

Presentational component

Photo by on

This is the basic type of component. It used for presenting, formatting data. It takes some properties and displays them in a more meaningful way. It shouldn’t be responsible for data fetching or business logic. One good example can be a component for displaying a user’s avatar.

Example definition:

// user-avatar/template.hbs
<img src={{user.avatarUrl}}>

Call API example:

{{user-avatar user=user}}

References:

Contextual component

Photo by on

These components can be used as a wrapper eg. for markup. They can act like any other component type. The only difference is that they can pass content inside of the block to a specific place in the component using the {{yield}} statement.

Example definition:

// page-header/template.hbs
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>{{yield}}</p>
</div>

Call API example:

{{#page-header}}
How are you?
{{/page-header}}

References:

Container component

Photo by on

This pattern is used for data manipulation, actions handling and all the business logic around. For example, it can fetch the user and format the content using presentational components. Container component can also act as the contextual component, allowing you to overwrite the content and markup by passing a block.

Example definition:

// user-profile/component.js
import Component from '';
import { inject as service } from '';
import { computed } from '';
export default Component.extend({
store: service(),
id: null,

user: computed('id', function() {
return id ? this.store.findRecord('user', this.id) : null;
}),
});
// user-profile/template.hbs
{{#if hasBlock}}
{{yield user}}
{{else}}
{{user.name}}
{{user-avatar user=user}}
{{/if}}

Call API example:

{{#user-profile id=7 as |user|}}
<h1>{{user.name}}</h1>
{{/user-profile}}

References:

Composable component (aka Higher-Order Component)

Photo by on

Its role is to deliver to you meaningful components/parts from which you can build your business logic and features but also serves as a great extension for container components. They should still stay flexible so you can add your own markup or modify behaviors. This kind of components can be used in a top-level template where you define your application layout but can be also used to form another component.

Example definition:

// articles-list/template.hbs
{{yield (hash
variables=(hash
articles=articles
)
components=(hash
list=(component "articles-list/list" articles=articles)
pagination=(component "articles-list/pagination")
)
)}}

Call API example:

{{#articles-list articles=user.articles as |articlesList|}}
{{#articlesList.components.list as |list|}}
{{#list.components.item as |article|}}
<h1>{{article.title}}</h1>
<p class="lead">{{article.body}}</p>
{{/list.components.item}}
{{/articlesList.components.list}}
{{articlesList.components.pagination}}
{{/articles-list}

References:


More about composable components soon in next articles :)


Of course, this is just an outline of these patterns but the point is to give an overview of which components pattern we can use during the development process of our application.

Any questions?
Twitter:


Hire me as your next frontend engineer!

Check out my projects, experience, and ask me a question on

Macsour

The Macsour blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store