To work with templates, we need to understand the basics on how properties bind with controllers and components. Here are a few recipes that go over how to accomplish this.
Before we get started, we'll need to generate a template.
$ ember new HelloWorldApp $ cd HelloWorldApp
This command will generate a new application that we can use for this recipe.
$ ember g route helloworld
This command will generate the template and routes file as well as unit tests. The template file is called helloworld.hbs
and will be generated in the app/templates
folder. The route file is called helloworld.js
and is located in the app/routes
folder. The route.js
file will also get modified with the new helloworld
route. We'll discuss more about routes in Chapter 4, Ember Router.
controller
:$ ember g controller helloworld
This will generate a new file called helloworld.js
in the app/controller
folder and a unit test in tests/unit/controllers
. We are now ready to continue.
Let's take a look at adding properties to our new template file.
helloworld.hbs
file. For this simple example, we'll create a string with the first and last name properties as follows:// app/templates/helloworld.hbs Hello World! My name is {{firstName}} {{lastName}}. {{outlet}}
Handlebar expressions are surrounded by double curly braces {{ }}
and backed by a context. A context is an object from which Handlebar expressions read their properties. In this example, the context is the controller. The {{outlet}}
will render the template of any nested routes, which will be discussed in more detail later.
firstName
and lastName
properties so that they can be displayed in the template:// app/controllers/helloworld.js import Ember from 'ember'; export default Ember.Controller.extend({ firstName: 'Erik', lastName: 'Hanchett' });
The controller has the same name as the template. The template, by convention, will retrieve the properties from the controller of the same name. Each of them is bound to each other. If any changes occur to the data, the other values will change.
Similar to controllers, we can create a component that can act as a context for the template. In the component, we can set up properties that can be accessed by the template later.
generate component
command:$ ember g component hello-world
All components must have a dash in their names. This command will create the hello-world.js
file in the app/components/hello-world.js
folder, a template file in the app/components/hello-world.hbs
file, and an integration test file at tests/integration/components/hello-world-test.js
.
hello-world.hbs
file and add the hello world string:// app/templates/components/hello-world.hbs Hello World! My name is {{firstName}} {{lastName}}. {{yield}}
The firstName
and lastName
parameters are retrieved from the component. The yield
expression is used when the component is in the block form. We'll talk more about this in Chapter 6, Ember Components.
hello-world.js
, the first one being firstName
and the last one being lastName
:// components/hello-world.js import Ember from 'ember'; export default Ember.Component.extend({ firstName: 'John', lastName: 'Smith' });
application.hbs
files:// app/templates/application.hbs <h2 id="title">Welcome to Ember</h2> {{hello-world}} {{outlet}}
The {{hello-world}}
Handlebar expression adds the component to the application.hbs
file. The hello-world
template will then be rendered here. The {{outlet}}
template will render the nested routes under the application
route.
http://localhost:4200
.http://localhost:4200/helloworld
and you'll be greeted with two messages. The message on the screen will show Hello World! My name is John Smith. Hello World! My name is Erik Hanchett.helloworld
route is loaded, the application template is displayed. The {{outlet}}
template then gets rendered with the contents of the helloworld
template file. This is why both messages are displayed. Remember that all routes are nested under the application
route.Ember.js uses the Handlebars templating library. This library provides you with a way to do data binding between the component or controller, also known as a context, and the template. This data binding occurs in both directions. In other words, changes to the data in the component or controller will be reflected in the template. Changes in the template to the data will be reflected in the controller or component.
In the previous simple example, the firstName
and lastName
properties in the component were accessed in the template with double curly braces {{}}
. This is known as a Handlebars expression. The template is just regular HTML with embedded Handlebar expressions. Ember compiles these templates later on during the build process.