A big part of the benefit of Ember is that an experienced Ember developer can quickly get up to speed and contribute to an existing project. So, there is most certainly a benefit in exercises that involve cloning an existing project and modifying them. This also permits us to avoid a bunch of setup commands and redundant work at the start of the episode. So today, we are going to clone a School Directory Project and add some features. In this project we once again have a contact model with some attributes, a contacts and contacts/contact route. We are also using Ember CLI Mirage to provide our development data and our fake 'API server'. Finally, we are using Bootstrap 4 for our css framework. Anyway, enough with the preliminaries, let's get going.

$ git clone https://github.com/baroquon/school-directory
$ cd school-directory
$ git checkout starting-point
$ npm install && bower install
$ ember s
[Visit localhost:4200](http://localhost:4200)

If we visit the contacts route you will notice that we have mixture of students and faculty in our list. We are using the same contact-card component to display their information. However, what if we want to see some information that is specific to a teacher or student? Say for students we want a list of their current courses and for teachers we want to see their education background. There are several ways to accomplish this. First let's generate our two components.

$ ember g component past-education && ember g component current-courses

First we'll open the current-courses template and modify it to look like we want:

In app/templates/components/current-courses.hbs: We'll pass in the contact so let's iterate over the contact's currentCourses and list the title, creditHours, and description. Adding this class so that Bootstrap will make it look pretty.

{{#each contact.currentCourses as |course|}}
  <li class='list-group-item'>
    <h4>{{course.title}}</h4>
    <p>Hours: {{course.creditHours}}</p>
    <p>{{course.description}}</p>
  </li>
{{/each}}

Now, in the component's JavaScript we'll just add a tagName and some class names.

import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'ul',
  classNames: ['list-group', 'list-group-flush']
});

Do basically the same thing for the teacher's component. In app/components/past-education.js we'll make it look the same as current-courses:

import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'ul',
  classNames: ['list-group', 'list-group-flush']
});

In the template, it will be similar, but we'll iterate over the contact's pastExperiences property and include that model's properties.

{{#each contact.pastExperiences as |experience|}}
  <li class='list-group-item'>
    <h4>{{experience.school}}</h4>
    <p>{{experience.degree}} - {{experience.major}}</p>
    <p>Minor: {{experience.minor}}</p>
  </li>
{{/each}}

Now let's open our contact-card template and add these new components. In app/templates/components/contact-card.hbs.

<div class="card-image-container">
  <img src="{{contact.avatar}}" class="card-img-top" alt="Card image cap">
</div>
<div class="card-block">
  <h4 class="card-title">{{contact.fullName}}</h4>
  <p class="card-text">{{contact.role}}</p>
  <p class="card-text"> <strong>phone:</strong> {{contact.phone}}</p>
  <p class="card-text"><strong>email:</strong> <a href="mailTo={{contact.email}}" class="card-link">{{contact.email}}</a> </p>
</div>

If we are going to display a different component depending on if our contact is a teacher or student we could use a simple conditional and just each component.

{{#if isTeacher}}
  {{past-education contact=contact}}
{{else}}
  {{current-courses contact=contact}}
{{/if}}

But, we don't need to. We can use Ember's component helper to get the correct component rendered.

{{component additionalInfo contact=contact}}

Now, we just need to create an 'additionalInfo' computed property that returns the name of the component we want to render as a string.

To accomplish this, open app/components/contact-card.js and add a computed property called

import Ember from 'ember';

export default Ember.Component.extend({
  classNames: 'card',
  additionalInfo: Ember.computed('contact.isTeacher', function(){
    if(this.get('contact.isTeacher')){
      return 'past-education';
    } else {
      return 'current-courses';
    }
  })
});

We have a computed property on the contact model called isTeacher that just returns true or false depending on the person's role.

That does it for now. We were able to get an existing Ember application up and running and we used the component helper to deal with branching UI needs based on data. We are going to continue iterating on this application for a while moving forward. In real life, we don't create a simple application and move on to other things, we spend most of our time iterating on existing applications. So, we will try and do some of that with this app.

Tomorrow we will look at building our application for production. The we will add pagination to our contacts list. See you then.

Notes

There are a few addons that allow you to easily integrate Bootstrap with your Ember CLI project. For this repo I tried both bennycwong/ember-bootstrap-4 and kaermorchen/ember-cli-bootstrap-4 and they were both perfectly fine. If you want to use Bootstrap 3 for a project you should check out ef4/ember-sass-bootstrap. It is also worth nothing that all of these depend on you having SASS available - see aexmachina/ember-cli-sass.