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

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; 
  } 
} 
主站蜘蛛池模板: 巴青县| 怀仁县| 沙坪坝区| 方正县| 新闻| 道孚县| 进贤县| 博湖县| 嘉兴市| SHOW| 博罗县| 金华市| 赤城县| 洛川县| 定州市| 潢川县| 桃园市| 绍兴县| 鸡东县| 温泉县| 类乌齐县| 柳林县| 涟源市| 上思县| 古蔺县| 泸西县| 庆安县| 邓州市| 义乌市| 北宁市| 东辽县| 江源县| 河间市| 隆尧县| 台安县| 娄烦县| 门头沟区| 满城县| 彰化县| 嵩明县| 中江县|