官术网_书友最值得收藏!

The main component

As you can see in the screenshot in the introduction of this chapter, this component should have a textbox, a button, and three tabs. Under the tabs, these component will show the forecast or the About page.

Using our other components

We can use our components that we have already written by adding them to the directives section and using their tag names in the template.

Two-way bindings

To get the value of the input box, we need two-way bindings. We can use the ngModel directive for that. The syntax combines the syntaxes of the two one-way bindings: [(ngModel)]="property". The directive is again a built-in one, so we don't have to import it.

Using this two-way binding, we can automatically update the weather widget after every key press. That would cause a lot of requests to the server, and especially on slow connections, that's not desired.

To prevent these issues, we will add two separate properties. The property location will contain the content of the input and activeLocation will contain the location, which is being shown.

Listening to our event

We can listen to our event, just like we did with other events. We can access the event content with $event. Such a listener will look like (correct-location)="correctLocation($event). When the server responds with the forecast, it also provides the name of the location. If the user had a small typo in the name, the response will correct that. This event will be fired in such a case and the name will be corrected in the input box.

Geolocation API

Because our forecast widget supports coordinates, we can use the geolocation API to set the initial location. That API can give the coordinates where the device is located (roughly). Later on, we will use this API to set the widget to the current location when the page loads as shown here:

navigator.geolocation.getCurrentPosition(position => { 
  const location = `Coordinate ${ position.coords.latitude }      ${ position.coords.longitude }`; 
  this.location = location; 
  this.activeLocation = location; 
}); 

Tip

Template string

Template strings, not to be confused with Angular templates, are strings wrapped in backticks (`). These strings can be multiline and can contain expressions between ${ and }.

Component sources

As usual, we start by importing Angular. We also have to import the two components we have already written. We use an enumeration again to store the state of the component:

import { Component } from "angular2/core"; 
import { Forecast } from "./forecast"; 
import { About } from "./about"; 
 
enum State { 
  Today, 
  Tomorrow, 
  About 
} 

The template will use the two-way binding on the input element:

@Component({ 
  selector: "weather-widget", 
  directives: [Forecast, About], 
  template: ` 
    <input [(ngModel)]="location" (keyup.enter)="clickGo()"        (blur)="clickGo()" /> 
    <button (click)="clickGo()">Go</button> 
     
    <div class="tabs"> 
      <a href="javascript:;" [class.selected]="selectedTab === 0"          (click)="selectTab(0)">Today</a> 
      <a href="javascript:;" [class.selected]="selectedTab === 1"          (click)="selectTab(1)">Tomorrow</a> 
      <a href="javascript:;" [class.selected]="selectedTab === 2"        (click)="selectTab(2)">About</a> 
    </div> 
     
    <div class="content" [class.is-dirty]="isDirty"      *ngIf="selectedTab === 0 || selectedTab === 1"> 
      <weather-forecast [location]="activeLocation"        [tomorrow]="selectedTab === 1"        (correctLocation)="correctLocation($event)" /> 
    </div> 
    <div class="content" *ngIf="selectedTab === 2"> 
      <about-page [location]="activeLocation" /> 
    </div> 
    `, 

Binding to class.selected means that the element will have the selected class if the bound value is true. After the template, we can add some styles as shown here:

  styles: [ 
    `.tabs > a { 
      display: inline-block; 
      padding: 5px; 
      margin-top: 5px; 
      border: 1px solid #57BEDE; 
      border-bottom: 0px none; 
      text-decoration: none; 
    } 
    .tabs>a.selected { 
      background-color: #57BEDE; 
      color: #fff; 
    } 
    .content { 
      border-top: 5px solid #57BEDE; 
    } 
    .is-dirty { 
      opacity: 0.4; 
      background-color: #ddd; 
    }` 
  ] 
}) 

In the constructor, we can use the geolocation API to get the coordinates of the current position:

export class Widget { 
  constructor() { 
    navigator.geolocation.getCurrentPosition(position => { 
      const location = `Coordinate ${ position.coords.latitude }          ${ position.coords.longitude }`; 
      this.location = location; 
      this.activeLocation = location; 
    }); 
  } 
 
  location: string = "Utrecht,NL"; 
  activeLocation: string = "Utrecht,NL"; 
  get isDirty() { 
    return this.location !== this.activeLocation; 
  } 
 
  clickGo() { 
    this.activeLocation = this.location; 
  } 
  correctLocation(location: string) { 
    if (!this.isDirty) this.location = location; 
    this.activeLocation = location; 
  } 
 
  selectedTab = 0; 
  selectTab(index: number) { 
    this.selectedTab = index; 
  } 
} 
主站蜘蛛池模板: 岳池县| 泰来县| 南投县| 黑河市| 牟定县| 泰州市| 从江县| 玉龙| 霍邱县| 织金县| 土默特左旗| 天水市| 平度市| 宽城| 双鸭山市| 永清县| 江山市| 修武县| 西充县| 罗平县| 光山县| 阳朔县| 旺苍县| 邵阳县| 合江县| 湄潭县| 永福县| 博白县| 榆林市| 东光县| 涞水县| 清河县| 乌拉特中旗| 本溪市| 察隅县| 朝阳区| 南木林县| 宣威市| 自治县| 亚东县| 阿巴嘎旗|