[null, {"document_url": "https://guides.emberjs.com/v2.18.0/tutorial/simple-component/", "unformatted_src": "/images/simple-component/app-with-images.png", "src": "https://guides.emberjs.com/images/simple-component/app-with-images.png", "formatted_filename": "app with images", "alt_text": "App with component and images"}, null, {"document_url": "https://guides.emberjs.com/v2.18.0/tutorial/simple-component/", "unformatted_src": "/images/simple-component/styled-rental-listings.png", "src": "https://guides.emberjs.com/images/simple-component/styled-rental-listings.png", "formatted_filename": "styled rental listings", "alt_text": "rental listing with expand"}, null]


Building a Simple Component

As a user looks through our list of rentals, they may want to have some interactive options to help them make a decision. Let's add the ability to toggle the size of the image for each rental. To do this, we'll use a component.

Let's generate a rental-listing component that will manage the behavior for each of our rentals. A dash is required in every component name to avoid conflicting with a possible HTML element, so rental-listing is acceptable but rental isn't.

Ember CLI will then generate a handful of files for our component:

A component consists of two parts:

Our new rental-listing component will manage how a user sees and interacts with a rental. To start, let's move the rental display details for a single rental from the rentals.hbs template into rental-listing.hbs and add the image field:

Now in our rentals.hbs template, let's replace the old HTML markup within our {{#each}} loop with our new rental-listing component:

Here we invoke the rental-listing component by name, and assign each rentalUnit as the rental attribute of the component.

Our app should behave now as before, with the addition of an image for each rental item. Hiding and Showing an Image

Now we can add functionality that will show the image of a rental when requested by the user.

Let's use the {{if}} helper to show our current rental image larger only when isWide is set to true, by setting the element class name to wide. We'll also add some text to indicate that the image can be clicked on, and wrap both with an anchor element, giving it the image class name so that our test can find it.

The value of isWide comes from our component's JavaScript file, in this case rental-listing.js. Since we want the image to be smaller at first, we will set the property to start as false:

To allow the user to widen the image, we will need to add an action that toggles the value of isWide. Let's call this action toggleImageSize

Clicking the anchor element will send the action to the component. Ember will then go into the actions hash and call the toggleImageSize function.

An actions hash is an object in the component that contains functions. These functions are called when the user interacts with the UI, such as clicking.

Let's create the toggleImageSize function and toggle the isWide property on our component:

Now when we click the image or the View Larger link in our browser, we see our image show larger. When we click the enlarged image again, we see it smaller. Move on to the next page for the next feature, or continue on here to test what you just wrote.


Ember components are commonly tested with component integration tests. Component integration tests verify the behavior of a component within the context of Ember's rendering engine. When running in an integration test, the component goes through its regular render lifecycle, and has access to dependent objects, loaded through Ember's resolver.

Our component integration test will test two different behaviors:

Let's update the default test to contain the scenarios we want to verify:

For the test we'll pass the component a fake object that has all the properties that our rental model has. We'll give the variable the name rental, and in each test we'll set rental to our local scope, represented by the this object. The render template can access values in local scope.

Now let's render our component using the render function. The render function allows us to pass a template string, so that we can declare the component in the same way we do in our templates. Since we set the rentalObj variable to our local scope, we can access it as part of our render string.

Finally, let's add our actions and assertions.

In the first test, we just want to verify the output of the component, so we just assert that the title and owner text match what we provided in the fake rental.

In the second test, we verify that clicking on the image toggles the size. We will assert that the component is initially rendered without the wide class name. Clicking the image will add the class wide to our element, and clicking it a second time will take the wide class away. Note that we find the image element using the CSS selector .image.

The final test should look as follows:

Run ember t -s to verify that our new test is passing. To find the new test, locate "Integration | Component | rental listing" in the "Module" field of the test UI.