A Programmer's Dream

Learning Ember -- Integrating Bootstrap

This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, part two started our first route, part three added a Click Event to the code while part four introduced components for code reuse. Today's section works on integrating Bootstrap into the framework. 
There is an Ember CLI element that does some of this work for you, but I just worked with integrating the artifacts from the Bootstrap website directly into my project.

To start with, I just worked with the CDN version of Bootstrap (https://getbootstrap.com) as I wanted to get it working before I worried about having downloaded artifacts. So, I first went to the getting started page for Bootstrap which provides the necessary links for CDN.

Then I opened up the index.html file to add the CDN references there, placing them between the content-for components for the "head" and "head-footer" in the HEAD section of this file.
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>EmberLearn</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">

{{content-for "head"}}

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"; integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">


<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"; integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"; integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"; integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
{{content-for "head-footer"}}

</head>

This means that the pages will include the Bootstrap elements as they're served. Now, my initial thought was that I'd be able to add the "container" DIV to this file, wrapping it around the content-for component for the body and body-footer. This didn't work. The EMBER content was served outside of the container DIV.

Instead, you need to open up the application.hbs, which is the global template for the Ember content, and add the container DIV here.
1
2
3
4
5
<div class="container">
<h1>Wish List</h1>

{{outlet}}
</div>

Elements like the NAVBAR could be implemented in either the index.html or application.hbs files.

But, this isn't the end of things. We now need to style our item-list component to display its content within the context of Bootstrap elements.

So, we open up the item-list component template file, and wrap the H2 element, and the UL elements within row DIVs and column DIVS
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="row">
<div class="col-12">
<h2>{{title}}</h2>
</div>
</div>
<div class='row'>
<div class="col-12">
<ul>
{{#each items as |item|}}
<li {{action "showItem" item}}><cite>{{item}}</cite></li>
{{/each}}
</ul>
</div>
</div>

This is a step in the right direction, but we also want the items to be displayed in a slightly better context as well. So, we'll switch the LI out for a DIV that implements the CARD class, and replace the UL with a DIV that implements he card-columns class. With a bit of CSS Styling, we end up with a nice set of boxed titles that still react to a user event.

Now, to make this server local assets for the Bootstrap libraries, for scenarios where you don't want functionality to change as things are updated, then you'd download the CSS and JS files and place them in the ASSETS folder of the application.

Then change the references to the CDN to reference "{{rootURL}}assets/" instead. Everything should just work at that point.
Bootstrap Cards

Learning Ember in VS Code -- Adding a Component

This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, part two started our first route  and part three added a Click Event to the code. Today's section works on adding a component to the system to allow for shared user interfaces.

As a programmer, I have to say that Ember components are awesome. These are user interface elements that can be shared in different places in the application. This means either on separate and distinct pages or multiple times on the same web page.

In this situation, I want to turn my list of items into an "item-list" template. Again, Ember has a generator to perform the slog work of boilerplate coding for you.

1
ember generate component item-list

This generator creates:
  1. a component JavaScript class (in app\components)
  2. the component's template (in app\templates\components)
  3. And of course a Unit Test
The first thing we need to do is move the code from our items route template over to our new item-list template. Next we want to parameterize the H2 element with the 'title' attribute. The final change is to modify the word model to the attribute "items."

The code in the item-list component template should read:

1
2
3
4
5
6
7
<h2>{{title}}</h2>

<ul>
{{#each items as |item|}}
<li {{action "showItem" item}}><cite>{{item}}</cite></li>
{{/each}}
</ul>

We also have to remember that the LI has an action associated with it. Thus, we need to move that action from the items route class to the item-list component class.

So, the item-list.js file needs to look like this:

 1
2
3
4
5
6
7
8
9
10
import Component from '@ember/component';

export default Component.extend({

actions: {
showItem(item) {
alert(item);
}
}
});

And the items.js file needs to end up looking like this:

1
2
3
4
5
6
7
import Route from '@ember/routing/route';

export default Route.extend({
model(){
return ['Friday', 'Dragon Riders of Pern', 'Foundation', 'Ringworld', 'RAMA'];
}
});

Then we need to return to the item route template, and wire it up to display our new component element.

1
{{item-list title="List of Books" items=model}}

What's going on here, is that the double curly braces indicate that this is a component, specifically the "item-list" component. The title used is the value passed into that attribute, while the array of items to use is passed into the items attribute, and is the model of the particular page.

In truth, the end result of this should show the exact page as previously, but components are an important concept to know as they allow for code re-usability.

The next entry will see about including Bootstrap into the framework.

Learning Ember in VS Code -- The First Event!


This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, part two started our first route and today we're actually going to have the application do something by having it respond to a mouse click.


Currently, the application shows a list. Not exactly ground breaking, or very useful.  So, what we need is to make the system respond to user interaction. Since this is the web, that interaction is a click event.  

To accomplish this, we add an action to the list item element in the items template.  The action helper takes in the name of the function to run, and the paramters for that function. for this function we'll name it "showItem" (and notice the casing for expected JavaScript styling) and pass it the item object that's referenced in the #each helper.

1
2
3
4
5
6
7
<h2>List of Items</h2>

<ul>
{{#each model as |item|}}
<li {{action "showItem" item}}><cite>{{item}}</cite></li>
{{/each}}
</ul>

The default behavior for the action helper is to add a click event listener to the associated HTML element. This means that clicking the LI element will call the showPerson function from the items route class.

This means we need to modify the items route class file to add this function definition. For now, all we'll do is use an alert dialog to display the book title, later we'll make changes to display more information about the item. 

 1
2
3
4
5
6
7
8
9
10
11
12
import Route from '@ember/routing/route';

export default Route.extend({
model(){
return ['Friday', 'Dragon Riders of Pern', 'Foundation', 'Ringworld', 'RAMA'];
}
, actions: {
showItem(item) {
alert(item);
}
}
});

So, now our application is actually doing something.
Ember Alert
Next time, we'll be introducing how to share things appropriately. 

Learning Ember in VS Code -- The First Route


This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, while today's section works on adding the first route to the system, where we display a list of items.
The first thing to do is modify the Application.hbs file (found in app/templates/application.hbs) and replace its contents with the below. 

1
2
3
<h1>Wish List</h1>

{{outlet}}

Now, we want to add a route to the system, specifically a route which provides a list of products that need to be shown. Luckily, Ember has a number of generators that make the creation of boilerplate code for common tasks simple and easy.  What this means in practice is that we need to run the below command inside our current Ember application's directory


1
ember generate route items

This command generates the template seen when the user visits the "/items" route, the actual route logic in the application router, and a route object which fetches the model to be used by the template. And you get a unit test. 
So, our first step is to go manipulate the template.  Open the "items.hbs" file found in app/templates and and an h2 tag with the text "Items."  An {{outlet}} line should already exist, and needs to remain for right now. 
After saving, you will be able to navigate to http://localhost:4200/items, and see the new page.
Of course, a template is not much use without the model to display the details of.  So, let's open up the items.js file from the "app/routes" folder.
The boilerplate has an import statement, and the standard extension statement.  We need to add a "model" method. The important part here is that the model method supports any library that uses JavaScript promises. For now, though, we just want to return a simple array.  So, modify the code until it looks like the below:

1
2
3
4
5
6
7
import Route from '@ember/routing/route';

export default Route.extend({
model() {
return ['Friday', 'Dragon Riders of Pern', 'Foundation', 'Ringworld', 'RAMA'];
}
});

Once that's changed, then the model is returning an array of items. In this case, a list of book titles.  Our next step is to tell Ember  how we want to display the array. We need to return to the items template, and add the code to make the program loop through the array and print its contents. 

1
2
3
4
5
6
7
<h2>Items</h2>

<ul>
{{#each model as |item|}}
<li><cite>{{item}}</cite></li>
{{/each}}
</ul>

So, using the "each" helper, we create a list of book titles, also notice the use of the "CITE" tag to emphasis that his is a title.