2014-02-06 13:33:42 +00:00
|
|
|
@ngdoc tutorial
|
2016-03-27 21:32:36 +03:00
|
|
|
@name 8 - Templating Links & Images
|
2014-02-06 13:33:42 +00:00
|
|
|
@step 8
|
2012-03-30 14:02:26 -07:00
|
|
|
@description
|
|
|
|
|
|
2012-04-28 22:45:28 -07:00
|
|
|
<ul doc-tutorial-nav="8"></ul>
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
In this step, we will add thumbnail images for the phones in the phone list, and links that, for
|
|
|
|
|
now, will go nowhere. In subsequent steps, we will use the links to display additional information
|
|
|
|
|
about the phones in the catalog.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
* There are now links and images of the phones in the list.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2014-04-04 14:05:24 +01:00
|
|
|
|
|
|
|
|
<div doc-tutorial-reset="8"></div>
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
## Data
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
Note that the `phones.json` file contains unique IDs and image URLs for each of the phones. The
|
|
|
|
|
URLs point to the `app/img/phones/` directory.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/phones/phones.json`** (sample snippet):
|
2014-02-06 14:02:18 +00:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
```json
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
...
|
|
|
|
|
"id": "motorola-defy-with-motoblur",
|
|
|
|
|
"imageUrl": "img/phones/motorola-defy-with-motoblur.0.jpg",
|
|
|
|
|
"name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
|
|
|
|
|
...
|
2012-03-30 14:02:26 -07:00
|
|
|
},
|
|
|
|
|
...
|
2016-03-27 21:32:36 +03:00
|
|
|
]
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
## Component Template
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`app/phone-list/phone-list.template.html`:**
|
2014-02-06 14:02:18 +00:00
|
|
|
|
|
|
|
|
```html
|
2016-03-27 21:32:36 +03:00
|
|
|
...
|
|
|
|
|
<ul class="phones">
|
|
|
|
|
<li ng-repeat="phone in $ctrl.phones | filter:$ctrl.query | orderBy:$ctrl.orderProp" class="thumbnail">
|
|
|
|
|
<a href="#/phones/{{phone.id}}" class="thumb">
|
|
|
|
|
<img ng-src="{{phone.imageUrl}}" alt="{{phone.name}}" />
|
|
|
|
|
</a>
|
|
|
|
|
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
|
|
|
|
|
<p>{{phone.snippet}}</p>
|
2012-03-30 14:02:26 -07:00
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
...
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
To dynamically generate links that will in the future lead to phone detail pages, we used the
|
|
|
|
|
now-familiar double-curly brace binding in the `href` attribute values. In step 2, we added the
|
|
|
|
|
`{{phone.name}}` binding as the element content. In this step the `{{phone.id}}` binding is used in
|
|
|
|
|
the element attribute.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
We also added phone images next to each record using an image tag with the {@link ngSrc ngSrc}
|
2017-01-24 17:23:54 +00:00
|
|
|
directive. That directive prevents the browser from treating the AngularJS `{{ expression }}` markup
|
2016-03-27 21:32:36 +03:00
|
|
|
literally, and initiating a request to an invalid URL (`http://localhost:8000/{{phone.imageUrl}}`),
|
|
|
|
|
which it would have done if we had only specified an attribute binding in a regular `src` attribute
|
|
|
|
|
(`<img src="{{phone.imageUrl}}">`). Using the `ngSrc` directive, prevents the browser from making an
|
|
|
|
|
HTTP request to an invalid location.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
# Testing
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<br />
|
|
|
|
|
**`e2e-tests/scenarios.js`**:
|
2014-02-06 14:02:18 +00:00
|
|
|
|
|
|
|
|
```js
|
2016-03-27 21:32:36 +03:00
|
|
|
...
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
it('should render phone specific links', function() {
|
|
|
|
|
var query = element(by.model('$ctrl.query'));
|
|
|
|
|
query.sendKeys('nexus');
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
element.all(by.css('.phones li a')).first().click();
|
|
|
|
|
expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s');
|
2012-03-30 14:02:26 -07:00
|
|
|
});
|
2016-03-27 21:32:36 +03:00
|
|
|
|
|
|
|
|
...
|
2014-02-06 14:02:18 +00:00
|
|
|
```
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
We added a new E2E test to verify that the application is generating correct links to the phone
|
|
|
|
|
views, that we will implement in the upcoming steps.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2014-04-01 11:13:22 -07:00
|
|
|
You can now rerun `npm run protractor` to see the tests run.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
2012-10-18 02:33:45 -07:00
|
|
|
|
2012-03-30 14:02:26 -07:00
|
|
|
# Experiments
|
|
|
|
|
|
2016-03-27 21:32:36 +03:00
|
|
|
<div></div>
|
|
|
|
|
|
|
|
|
|
* Replace the `ngSrc` directive with a plain old `src` attribute. Using tools such as your browser's
|
|
|
|
|
developer tools or inspecting the web server access logs, confirm that the application is indeed
|
|
|
|
|
making an extraneous request to `%7B%7Bphone.imageUrl%7D%7D` (or `{{phone.imageUrl}}`).
|
|
|
|
|
|
|
|
|
|
The issue here is that the browser will fire a request for that invalid image address as soon as
|
2017-01-24 17:23:54 +00:00
|
|
|
it hits the `<img>` tag, which is before AngularJS has a chance to evaluate the expression and
|
2016-03-27 21:32:36 +03:00
|
|
|
inject the valid address.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# Summary
|
|
|
|
|
|
2017-01-24 17:23:54 +00:00
|
|
|
Now that you have added phone images and links, go to {@link step_09 step 9} to learn about AngularJS
|
|
|
|
|
layout templates and how AngularJS makes it easy to create applications that have multiple views.
|
2012-03-30 14:02:26 -07:00
|
|
|
|
|
|
|
|
|
2012-04-28 22:45:28 -07:00
|
|
|
<ul doc-tutorial-nav="8"></ul>
|