The goal of the the first four chapters was to jump-start application development with Angular.
最初の4つの章の目標は、Angularを使用してアプリケーション開発を開始することでした。
In those chapters we used property bindings, handled events, and applied directives without providing detailed explanations.
これらの章では、プロパティのバインディング、イベントの処理、およびディレクティブの適用について説明しませんでした。
In this chapter we want to take a breather and cover some of the techniques we used in more detail.
この章では、息をのむようにし、私たちが使用した技術のいくつかについて詳しく説明します。
We’ll continue writing code in TypeScript, and you’ll see an example of using destructuring syntax while handing events.
TypeScriptにコードを書き続けます。イベントを渡している間に非構造化構文を使用する例があります。
Data binding allows you to connect the data from your application with the UI, and the data-binding syntax lowers the amount of manual coding.
データバインディングを使用すると、アプリケーションのデータをUIに接続することができ、データバインディング構文は手作業によるコーディングの量を削減します。
In chapter 2 we briefly introduced the data-binding syntax and we used it in almost every example in the previous chapters.
第2章では、データバインディングの構文を簡単に紹介し、これまでの章のほぼすべての例で使用しました。
In particular, you’ve seen the following examples:
特に、次の例を見てきました。
<!-- Displaying a value or an expression as a string in a template -->
<!-- 値または式をテンプレートに文字列として表示する。 -->
<h1>Hello {{ name }}!</h1>
<!-- Using square brackets to bind an HTML element's properties -->
<!-- 角括弧を使用してHTML要素のプロパティをバインドする -->
<span [hidden]="isValid">This field is required</span>
<!-- Binding to events with parentheses -->
<!-- カッコでイベントにバインドする。 -->
<button (click)="placeBid()">Place Bid</button>
In Angular, data binding is implemented in a unidirectional way (also known as one-way data binding).
Angularでは、データバインディングは単方向(単方向データバインディングとも呼ばれます)で実装されています。
The “one way” could mean either applying data changes from the component’s properties to the UI or binding UI events with the component’s methods.
「一方通行」とは、コンポーネントのプロパティからのデータ変更をUIに適用するか、コンポーネントのメソッドでUIイベントをバインドすることです。
For example, whenever a component’s property is updated, productTitle the view (the template) is automatically updated by using the following syntax in the template: {{productTitle}}.
たとえば、コンポーネントのプロパティが更新されるたびに、productTitleビュー(テンプレート)はテンプレート内の次の構文 {{productTitle}}
を使用して自動的に更新されます。
Similarly, when a user types in an field, the event binding (denoted by parentheses) invokes an event handler on the right side of the equal sign:
同様に、ユーザーがフィールドに入力すると、イベントバインディング(カッコで示されます)は等号の右側にイベントハンドラを呼び出します。
(input)="onInput()"
In templates, both double curly braces in the text and square brackets in HTML elements’ attributes result in property binding.
テンプレートでは、HTML要素の属性の中の二重中括弧と大括弧の両方がプロパティバインドになります。
Angular binds the interpolated value (a string with injected expression values) to the textContent property of the corresponding DOM node.
Angularは、対応するDOMノードのtextContentプロパティに、補間された値(挿入された式の値を含む文字列)をバインドします。
It’s not just a one-time assignment—the text is constantly updated as the value of the corresponding expression changes.
1回限りの割り当てではなく、対応する式の値が変わるたびにテキストが常に更新されます。
In AngularJS, data changes on the view automatically update the underlying data (one direction), which also triggers an update of the view(another direction).
AngularJSでは、ビュー上のデータ変更によって、基礎となるデータ(一方向)が自動的に更新され、ビューの更新(別の方向)もトリガーされます。
In other words, AngularJS uses two-way data binding under the hood.
言い換えれば、AngularJSはボンネットの下で双方向データバインディングを使用します。
Although having two-way data binding in forms simplifies coding, using it to bind values in various application scripts may substantially slow performance in large applications.
フォームで双方向データ・バインディングを使用すると、コーディングが簡単になりますが、さまざまなアプリケーション・スクリプトで値をバインドすると、大規模アプリケーションでパフォーマンスが大幅に低下する可能性があります。
That’s because AngularJS internally keeps a list of all data binding expressions on the page, and a browser event can result in AngularJS checking the list of the expressions over and over again until it ensures that everything is in sync.
これは、AngularJSが内部的にページ上のすべてのデータバインディング式のリストを保持し、ブラウザイベントがAngularJSが繰り返し式のリストを何度もチェックして、すべてが同期していることを保証するまでです。
During this process, a single property can be updated multiple times.
このプロセス中に、1つのプロパティを複数回更新することができます。
Although Angular doesn’t use two-way data binding by default, you can still implement it.
Angularはデフォルトで双方向データバインディングを使用しませんが、実装することはできます。
Now it’s your choice, not the framework’s.
今はあなたの選択であり、フレームワークではありません。
In this section we’ll go over several flavors of data binding:
このセクションでは、データバインディングのいくつかのフレーバーについて説明します。
- Event binding to invoke a function that handles this event (このイベントを処理する関数を呼び出すイベントバインディング)
- Attribute binding to update the text value of an HTML element’s attribute (HTML要素の属性のテキスト値を更新する属性バインディング)
- Property binding to update the value of the DOM element’s property (DOM要素のプロパティの値を更新するプロパティバインディング)
- Template binding to transform the view template (ビューテンプレートを変換するテンプレートバインディング)
- Two-way data binding with ngModel (ngModelによる双方向データバインディング)
To assign an event handler function to an event, you need to put the event name in parentheses in the component’s template.
イベントハンドラ関数をイベントに割り当てるには、コンポーネントのテンプレートのカッコ内にイベント名を配置する必要があります。
The following code snippet shows how to bind the function to the event, and
onClickEvent()
click the functiononInputEvent()
to the input event.
次のコードスニペットは、関数をイベントにバインドする方法を示しています。 そして、onClickEvent()
をクリックすると、入力イベントに対して onInputEvent()
という関数が呼び出されます。
<button (click)="onClickEvent()">Get Products</button>
<input placeholder= "Product name" (input)="onInputEvent()">
When the event specified in parentheses is triggered, the expression in the double quotes is re-evaluated.
カッコで指定されたイベントがトリガされると、二重引用符で囲まれた式が再評価されます。
In the preceding examples, the expressions are functions, so they’re invoked each time the corresponding event is triggered.
前の例では、式は関数なので、対応するイベントがトリガされるたびに呼び出されます。
If you’re interested in analyzing the properties of the event object, just add the $event argument to the handler function.
イベントオブジェクトのプロパティの分析に興味がある場合は、ハンドラ関数に $event引数を追加するだけです。
In particular, the target property of the event object represents the DOM node where the event occurred.
特に、イベントオブジェクトのtargetプロパティは、イベントが発生したDOMノードを表します。
The instance of the event object will be available only within the binding scope (that is, in the event handler function).
イベントオブジェクトのインスタンスは、バインディングスコープ内(つまり、イベントハンドラ関数内)でのみ使用できます。
Figure 5.1 shows how to read the event-binding syntax.
図5.1に、イベント・バインディング構文を読み取る方法を示します。
Figure 5.1 Event-binding syntax
図5.1 イベントバインディング構文
<input (input)="onInputEvent($event)">
- (input) = Parentheses denote the event binding (カッコはイベントバインディングを示します)
- input = An arbitrary event name (任意のイベント名)
- onInputEvent($event) = An expression to execute when the event occurs (イベントが発生したときに実行する式)
- onInputEvent = The components's method name (コンポーネントのメソッド名)
- $event = An object representing the native browser event (ネイティブブラウザイベントを表すオブジェクト)
The name of the event in parentheses is called the target of binding.
カッコ内のイベントの名前をバインディングのターゲットと呼びます。
You can bind functions to any standard DOM events that exist today (see the Mozilla Developer Network documentation for the “Event reference,” http://mzl.la/1JcBR22) or that will be introduced in the future.
今日存在する標準のDOMイベントに関数をバインドすることができます(「イベントリファレンス」http://mzl.la/1JcBR22のMozilla Developer Networkのドキュメントを参照)、または今後導入される予定です。
You can also create custom events and bind function handlers to them in the same way (see the section in chapter 6 titled “Output properties and custom events”).
カスタムイベントを作成し、同じ方法で関数ハンドラをバインドすることもできます(第6章「出力プロパティとカスタムイベント」のセクションを参照)。
Each HTML element is represented by a tag with attributes, and the browser creates a DOM object with properties for each tag.
各HTML要素は属性を持つタグで表され、ブラウザは各タグのプロパティを持つDOMオブジェクトを作成します。
The user sees DOM objects on the screen as they’re rendered by the browser.
ユーザーはブラウザでレンダリングされているときにDOMオブジェクトを画面に表示します。
You should have a good understanding of what exists at any given moment in the three distinct areas:
あなたは、3つの異なった分野のどの瞬間に存在するかをよく理解する必要があります:
Angular updates DOM through the one-way property binding.
Angularは、一方向のプロパティーバインディングを介してDOMを更新します。
Property binding does not update the HTML element.
プロパティーのバインディングは、HTML要素を更新しません。
- The HTML document (HTMLドキュメント)
- The DOM object (DOMオブジェクト)
- The rendered UI (描画されるUI)
An HTML document consists of elements that are represented by tags with attributes, which are always strings.
HTML文書は、常に文字列である属性を持つタグで表される要素で構成されています。
The browser instantiates HTML elements as DOM objects (nodes) that have properties and are rendered on the web page as a UI.
ブラウザは、プロパティを持ちUIとしてWebページにレンダリングされるDOMオブジェクト(ノード)としてHTML要素をインスタンス化します。
Whenever the values of the DOM nodes’ properties change, the page is re-rendered.
DOMノードのプロパティの値が変更されるたびに、ページが再レンダリングされます。
Consider the following tag:
次のタグを考えてみましょう。
<input type="text" value="John" required>
The browser uses this string to create a node in the DOM tree, which is a JavaScript object of type HTMLInputElement.
ブラウザはこの文字列を使用して、DOMツリー内にHTMLInputElement型のJavaScriptオブジェクトであるノードを作成します。
Each DOM object has an API in the form of methods and properties (see the Mozilla Developer Network documentation for “HTMLInputElement,” http://mzl.la/1QqMBgQ).
各DOMオブジェクトには、メソッドとプロパティの形式でAPIが用意されています(「HTMLInputElement」http://mzl.la/1QqMBgQのMozilla Developer Networkのドキュメントを参照)。
In particular, the HTMLInputElement object includes the properties type and value of type 'DOMString', and 'required' of type Boolean.
特に、HTMLInputElementオブジェクトには、 'DOMString'タイプのプロパティタイプと値、およびBooleanタイプの 'required'プロパティが含まれています。
The browser renders this DOM node.
ブラウザはこのDOMノードをレンダリングします。
The browser will synchronize the rendered values with the values of the corresponding DOM object’s properties, regardless of the synchronization features offered by a particular framework.
ブラウザは、特定のフレームワークによって提供される同期機能に関係なく、レンダリングされた値を対応するDOMオブジェクトのプロパティの値と同期させます。
In Angular you denote property binding by enclosing the property name in square brackets and assigning an expression (or a class variable) to it.
Angularでは、プロパティ名を角カッコで囲み、式(またはクラス変数)を代入することによって、プロパティのバインディングを示します。
Figure 5.2 illustrates how Angular’s property-binding mechanism works.
図5.2は、Angularのプロパティーバインディングの仕組みを示しています。
Imagine a component, MyComponent, that has a class with a variable greeting.
変数greetingを持つクラスを持つMyComponentコンポーネントを想像してみてください。
The template of this component includes an
<input>
tag with the class variable greeting bound to the property value.
このコンポーネントのテンプレートには、プロパティ値にバインドされたクラス変数greetingを含む <input>
タグが含まれています。
- Angular updates DOM throguh the one-way property binding.(Angularは、一方向のプロパティバインディングをDOMに更新します。)
- Property binding does not update the HTML element.(プロパティーのバインディングはHTML要素を更新しません。)
- DOM node's "value" property is displayed on UI. Browser keeps UI and DOM in sync.(DOMノードのvalueプロパティがUIに表示されます。 ブラウザは、UIとDOMを同期させて保持します。)
- DOM node's "value" property doesn't change the corresponding element's attribute.(DOMノードのvalueプロパティは、対応する要素の属性を変更しません。)
- Browser doesn't sync HTML element's attribute with UI when user types the text.(5.ユーザーがテキストを入力すると、ブラウザはHTML要素の属性をUIと同期させません。)
Typesetter: The following numbered points go with the cueballs in the figure.
Typesetter:次の番号のポイントは、図のキューボールと一緒に行きます。
They can be treated as labels to add to the figure, or as a list of cueballs following the figure—whatever works best.
彼らは、図に追加するラベルとして扱うことができます。または、図に続くキューボールのリストとして扱うことができます。
- Angular updates the DOM using the one-way property binding (from greeting to the DOM object’s property). If a script assigns a reference to this
<input>
element to the variable inputElement, it’s going to be equal to A value. Note that we use dot notation to access the value of the node’s property.(Angularは、(greetingからDOMオブジェクトのプロパティへ)一方向のプロパティバインディングを使用してDOMを更新します。 スクリプトがこの<input>
要素への参照を変数inputElementに代入すると、それはAの値に等しくなります。 ドット記法を使用して、ノードのプロパティの値にアクセスすることに注意してください。) - Angular’s property binding doesn’t update the attribute of the HTML element after the value of inputElement.value changes.(Angularプロパティバインディングは、inputElement.valueの値が変更された後にHTML要素の属性を更新しません。)
- The DOM node’s value property is displayed on the UI. Angular updated the DOM node, and browser rendered the new value to keep the DOM and UI in sync.(DOMノードのvalueプロパティがUIに表示されます。 AngularはDOMノードを更新し、ブラウザは新しい値をレンダリングしてDOMとUIを同期させました。)
- The DOM node’s value property doesn’t change the attribute of the corresponding HTML element.(DOMノードのvalueプロパティは、対応するHTML要素の属性を変更しません。)
- The browser doesn’t sync the HTML element’s attribute with the UI when the user types in the
<input>
. The user sees the new values coming from the DOM and not from the HTML document.(ユーザーが<input>
をタイプすると、ブラウザはHTML要素の属性をUIと同期させません。 新しい値は、HTMLドキュメントからではなくDOMから取得されます。)
An application component may have a data structure that serves as a model.
アプリケーションコンポーネントは、モデルとして機能するデータ構造を有することができる。
Application code may also change the model’s property (such as a function that calculates something, or data coming from a server), which will trigger the property-binding mechanism, resulting in UI updates.
アプリケーションコードは、モデルのプロパティ(何かを計算する関数やサーバからのデータなど)を変更し、プロパティバインドの仕組みをトリガしてUIの更新を行うこともあります。
Property binding is used in two scenarios:
プロパティのバインドは、次の2つのシナリオで使用されます。
A component needs to reflect the state of the model in the view.
コンポーネントは、ビュー内のモデルの状態を反映する必要がある場合
A parent component needs to update a property of its child (see the “Input Properties” section in chapter 6).
親コンポーネントは、その子のプロパティを更新する必要がある場合(第6章の「入力プロパティ」を参照)。
We use the word in the context of the HTML document (attributes not the DOM object).
HTML文書(DOMオブジェクトではない属性)のコンテキストでこの単語を使用します。
Attribute bindings are rarely used, because the browser uses HTML to build the DOM tree, and after that it works mainly with properties of the DOM object.
ブラウザはHTMLを使用してDOMツリーを構築し、その後は主にDOMオブジェクトのプロパティで動作するため、属性バインディングはめったに使用されません。
But there are some cases when you may need to use attribute bindings.
しかし、属性バインディングを使用する必要がある場合があります。
For example, the hidden attribute isn’t supported in Internet Explorer 10, and it won’t create a corresponding DOM attribute, so if you need to toggle the visibility of a component using CSS styles, attribute binding will help.
たとえば、Internet Explorer 10では非表示属性がサポートされていないため、対応するDOM属性が作成されないため、CSSスタイルを使用してコンポーネントの表示を切り替える必要がある場合は、属性バインディングが役立ちます。
Another example is integration with the Google Polymer framework—we could only do it via attribute binding.
もう1つの例は、Google Polymerフレームワークとの統合です。属性バインディングを使用してのみ行うことができます。
Like property bindings, the attribute binding is denoted by placing an attribute name in square brackets.
プロパティバインディングと同様に、属性バインディングは、属性名を角括弧で囲むことで表されます。
But to let Angular know that you want to bind to an attribute (and not the DOM property), you have to add the prefix attr.:
しかしAngularに、(DOMプロパティではなく)属性にバインドすることを知らせるには、接頭辞attrを追加する必要があります。
<input [attr.value]="greeting">
Figure 5.3 illustrates attribute binding.
図5.3は、属性の結合を示しています。
- Angular updates HTML element through the one-way attribute binding.(Angularは、一方向の属性バインディングを介してHTML要素を更新します。)
- Attribute binding does not update the DOM node.(属性バインディングはDOMノードを更新しません。)
- Browser syncs HTML input element's "value" attribute with the corresponding DOM node's property.(ブラウザは、HTML入力要素の「value」属性を、対応するDOMノードのプロパティと同期させます。)
- DOM node's "value" property is displayed on UI. Browser keeps UI and DOM in sync.(ブラウザは、HTML入力要素の「value」属性を、対応するDOMノードのプロパティと同期させます。)
Typesetter: The following numbered points go with the cueballs in the figure.
Typesetter:次の番号のポイントは、図のキューボールと一緒に行きます。
They can be treated as labels to add to the figure, or as a list of cueballs following the figure—whatever works best.
彼らは、図に追加するラベルとして扱うことができます。または、図に続くキューボールのリストとして扱うことができます。
- Angular updates the HTML element using the one-way attribute binding (from greeting to the HTML element’s attribute). Note the attr. in the binding expression.(Angularは一方向の属性バインディング(挨拶からHTML要素の属性へ)を使用してHTML要素を更新します。 attrに注意してください。 結合表現で。)
- Angular’s attribute binding doesn’t update the DOM’s node.(Angularの属性バインディングは、DOMのノードを更新しません。)
- In this case, the DOM’s object got A value because the browser synchronized the value attribute between the HTML element and the DOM.(この場合、ブラウザはHTML要素とDOMの間でvalue属性を同期させたため、DOMのオブジェクトには値が返されます。)
- The DOM node’s value property is displayed on the UI because the browser keeps theUI and DOM in sync.(ブラウザがUIとDOMを同期させて保持するため、DOMノードのvalueプロパティがUIに表示されます。)
Let’s see how the property and attribute bindings work in a simple example.
簡単な例で、プロパティと属性のバインディングがどのように機能するかを見てみましょう。
Thefollowing code shows an
<input>
element that uses binding with the attribute value and the property value.
次のコードは、属性値とプロパティ値とのバインディングを使用する <input>
要素を示しています。
This code sample is located in the attribute-vs-property.ts file:
このコードサンプルは、attribute-vs-property.tsファイルにあります。
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@Component({
selector: 'app',
template: `
<h3>Property vs attribute binding:</h3>
<input [value]="greeting" // (1)
[attr.value] = "greeting" // (2)
(input)="onInputEvent($event)"> // (3)
`
})
class AppComponent {
greeting: string = 'A value';
onInputEvent(event: Event): void {
let inputElement: HTMLInputElement = <HTMLInputElement> event.target; // (4)
console.log(`The input property value = ${inputElement.value}`);
console.log(`The input attribute value = ${inputElement.getAttribute('value')}`); // (5)
console.log(`The greeting property value = ${this.greeting}`);
}
}
@NgModule({
imports: [ BrowserModule],
declarations: [ AppComponent],
bootstrap: [ AppComponent ]
})
class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
(1) This is property binding.
(1)これはプロパティバインディングです。
(2) This is attribute binding.
(2)これは属性バインディングです。
(3) Binding a standard DOM input event, which is fired when the value of the
<input>
element is changed.
(3)標準DOM入力イベントをバインドする。これは、<input>
要素の値が変更されたときに発生する。
(4) The
onInputEvent()
event handler received the Event object, and its target property has a reference to the element where this event occurred.
(4) onInputEvent()
イベントハンドラはEventオブジェクトを受け取り、targetプロパティはこのイベントが発生した要素への参照を持ちます。
(5)We use
getAttribute()
to get the attribute’s value, while properties are accessible, using the dot notation.
(5) getAttribute()
を使用して属性の値を取得し、プロパティにアクセスできるようにドット表記を使用します。
If you run this program and start typing in the input field, it’ll print on the browser console the content of the DOM’s property, the attribute value value of the HTML
<input>
element, and the content of the greeting property of MyComponent.
このプログラムを実行して入力フィールドに入力を開始すると、ブラウザのコンソールにDOMのプロパティの内容、HTMLの <input>
要素の属性値の値、および MyComponentのプロパティgreeting
の内容が出力されます。
Figure 5.4 shows the console output after we started this program and typed “3” in the
<input>
field.
図5.4は、このプログラムを開始した後のコンソール出力を示し、<input>
フィールドに "3"をタイプしたものです。
The value of the attribute didn’t change.
属性の値は変更されませんでした。
The value value of greeting isn’t changed either, which proves that Angular doesn’t use two-way data binding.
グリーティングの値の値も変更されません。これは、Angularが双方向データバインディングを使用していないことを示しています。
In AngularJS, changing the model (greeting), would update the view, and if the user changed the data on the view, it would automatically update the model.
AngularJSでは、モデル(グリーティング)を変更するとビューが更新され、ユーザーがビュー上のデータを変更した場合、モデルが自動的に更新されます。
In appendix A we cover the ES6 destructuring feature, which is supported by TypeScript as well.
付録Aでは、TypeScriptでサポートされているES6非構造化機能についても説明します。
Destructuring could simplify the code of the event handler function onInputEvent()
in the preceding code sample.
非構造化は、前のコードサンプルのイベントハンドラ関数onInputEvent()のコードを単純化することができます。
The onInputEvent()
function receives the Event object, and then a line extracts the value from target property. With destructuring syntax, we could eliminate this line:
onInputEvent()
関数はEventオブジェクトを受け取り、その行はtargetプロパティから値を抽出します。 非構造化構文では、その行を削除できます。
onInputEvent({target}): void {
console.log(`The input property value = ${target.value}`);
console.log(`The input attribute value = ${target.getAttribute('value')}`);
console.log(`The greeting property value = ${this.greeting}`);
}
Using the curly braces in the argument of this function sends the following instruction to this function: “You’ll get an object that has a target property. Just give me the value of this property.”
この関数の引数に中括弧を使用すると、次の命令がこの関数に送信されます。"ターゲットプロパティを持つオブジェクトを取得します。 ただ私にこのプロパティの値を教えてください。"
Say you need to conditionally hide or show a certain HTML element.
特定のHTML要素を条件付きで非表示または表示する必要があるとします。
You can do it by binding a Boolean flag to a hidden attribute or a display style of the element.
ブール値フラグを要素の隠し属性または表示スタイルにバインドすることで、これを行うことができます。
Depending on the flag’s value, this element will either be shown or hidden, but the object that represents this element remains in the DOM tree.
フラグの値に応じて、この要素は表示または非表示になりますが、この要素を表すオブジェクトはDOMツリーに残ります。
Angular offers structural directives (
NgIf
,NgSwitch
, andNgFor
) that change the DOM’s structure by removing or adding elements to it.
Angularは、要素を削除または追加することによってDOMの構造を変更する構造ディレクティブ( NgIf
、 NgSwitch
、および NgFor
)を提供します。
NgIf
can conditionally remove an element from or add one to the DOM tree.
NgIf
は条件付きでDOMツリーから要素を削除したり、DOMツリーに追加したりすることができます。
NgFor
loops through an array and adds an element to the DOM tree for each array element.
NgFor
は配列をループし、各配列要素のDOMツリーに要素を追加します。
adds
NgSwitch
one element to the DOM tree from a set of possible elements, based on some condition.
いくつかの条件に基づいて、可能な要素のセットからDOMツリーに NgSwitch
要素を追加します。
Using template binding, you can instruct Angular to do this for you.
テンプレートバインディングを使用すると、これを行うためにAngularに指示することができます。
Removing elements can be better than hiding them if you want to ensure that your application won’t waste time supporting the behavior of these elements (such as processing events or monitoring change detection).
アプリケーションがイベントの処理や変更の検出の監視など、これらの要素の動作をサポートする時間を無駄にしないようにするには、要素を隠すよりも要素を削除するほうが良いでしょう。
The HTML
<template>
tag (see the Mozilla Developer Network documentation for<template>
, http://mzl.la/1OndeMV ) is not a typical tag because the browser ignores its content unless the application includes a script to parse and add it to the DOM.
HTMLの <template>
タグ(<template>
は、Mozilla Developer Networkのドキュメント( http://mzl.la/1OndeMV )を参照)は典型的なタグではありません。なぜなら、アプリケーションがDOMを解析してDOMに追加するスクリプトを含まない限り、ブラウザはその内容を無視するからです。
Angular offers so-called shortcut syntaxes for directives—they start with an asterisk, such as
*ngIf
or*ngFor
.
Angularは、ディレクティブのショートカットシンタックス( * ngIf
や * ngFor
などのアスタリスクで始まります)を提供します。
When Angular’s parser sees a directive that starts with an asterisk, it converts this directive into an HTML fragment that uses a
<template>
tag and is recognizable by browsers.
Angularのパーサーはアスタリスクで始まるディレクティブを見ると、このディレクティブをHTMLフラグメントに変換します。このフラグメントは <template>
タグを使用し、ブラウザによって認識されます。
The following code sample (template-binding.ts) includes one
<span>
and one<template>
, and it illustrates two flavors of template binding using theNgIf
directive.
次のコードサンプル(template-binding.ts)は、 <span>
と <template>
を含み、 NgIf
指示文を使って2つのテンプレートバインディングを示しています。
Depending on the flag’s value (which is toggled by the button click) the
<span>
elements either add to the DOM or remove from it.
フラグの値(ボタンのクリックによってトグルされます)に応じて、 <span>
要素はDOMに追加するか、そこから削除します。
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@Component({
selector: 'app',
template: `
<button (click)="flag = !flag">Toggle flag's value</button>
<p>
Flag's value: {{flag}}
</p>
<p>
1. span with *ngIf="flag": <span *ngIf="flag">Flag is true</span>
</p>
<p>
2. template with [ngIf]="flag": <template [ngIf]="flag">Flag is true</template>
</p>
`
})
class AppComponent {
flag: boolean = true;
}
@NgModule({
imports: [ BrowserModule],
declarations: [ AppComponent],
bootstrap: [ AppComponent ]
})
class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
Unlike other Angular bindings, the template binding transforms the view template.
他のAngularバインディングとは異なり、テンプレートバインディングはビューテンプレートを変換します。
The preceding example conditionally adds or removes the message about the flag’s value from the DOM tree.
上記の例では、DOMツリーからフラグの値に関するメッセージを条件付きで追加または削除しています。
In this example we used both the shortcut syntax,
*ngIf="flag"
, to handle the<span>
element and a fully expanded version,[ngIf]="flag"
, to handle the content of the<template>
tag.
この例では、ショートカット構文 * ngIf =" flag "
と、完全拡張バージョン [ngIf] =" flag "
を使用して、 <template>
タグです。
Figure 5.5 shows that when the flag is true, the DOM tree includes the content of both
<span>
and<template>
.
図5.5に示すように、フラグがtrueの場合、DOMツリーには<span>
と<template>
の両方の内容が含まれています。
Figure 5.6 shows that when the flag is false, the DOM tree doesn’t include either
<span>
or<template>
.
図5.6は、フラグがfalseの場合、DOMツリーに <span>
または <template>
が含まれていないことを示しています。
All of the binding examples you’ve seen so far illustrate binding in one direction: either from the UI to the application code, or from the code to the UI. But there’s another scenario in which binding works in both directions, and we’ll discuss it next.
あなたが今見たバインディングの例はすべて、一方向のバインディングを示しています: UIからアプリケーションコードへ、またはコードからUIへのいずれかを選択します。 しかしバインディングが両方向で動作する別のシナリオがあります。次にこれについて説明します。
Two-way data binding is a simple way to keep the view and the model in sync. Whether the view or the model change first, both are immediately synchronized.
双方向データ・バインディングは、ビューとモデルを同期させておくための簡単な方法です。 ビューまたはモデルが最初に変更されるかどうかにかかわらず、両方がすぐに同期されます。
You learned that the one-way binding from the UI to an Angular component is arranged by surrounding an event name with parentheses:
UIからAngularコンポーネントへの一方向バインディングは、イベント名をかっこで囲むことで配置されていることが分かりました。
<input (input)="onInputEvent($event)">
One-way binding from a component to the UI is denoted by surrounding an HTML attribute with square brackets:
コンポーネントからUIへの一方向バインディングは、角括弧で囲まれたHTML属性で囲まれています:
<input [value]="myComponentProperty">
In some cases, you may still want to use two-way binding.
場合によっては、双方向バインディングを使用することができます。
The longer way of combining the two preceding code samples would be as follows:
上記の2つのコードサンプルを結合する方法は、次のようになります:
<input [value]="myComponentProperty" (input)="onInputEvent($event)">
Angular also offers a shorter combined notation.
[()]
:
Angularは組み合わせ表記も短くします。 [()]
:
In particular, Angular has a
NgModel
directive that you can use for two-way binding (note that whenNgModel
is used in templates, its name isn’t capitalized):
特に、Angularには、双方向バインディングに使用できる NgModel
ディレクティブがあります(NgModel
がテンプレートで使用されるとき、その名前は大文字になりません)。
<input [(ngModel)] = "myComponentProperty">
In this shorter notation example, you can still see
myComponentProperty
, but which event does it handle? In this example, theNgModel
directive is used with the<input>
element.
この短い表記の例では、 myComponentProperty
を見ることができますが、どのイベントが処理しますか?この例では、 NgModel
指示文が<input>
要素とともに使用されています。
This event is the default trigger for synchronizing the UI changes in the the HTML
<input>
element with the underlying model.
このイベントは、HTMLの<input>
要素のUI変更を基になるモデルと同期するためのデフォルトのトリガーです。
But the driving event can be different, depending on the UI control being used with
ngModel
.
しかし、運ぶイベントは、 ngModel
で使用されているUIコントロールによって異なる場合があります。
This is controlled internally by a special
ControlValueAccessor
Angular interface, which serves as a bridge between a control and a native element.
これは、コントロールとネイティブ要素の間のブリッジとして機能する特殊なControlValueAccessor
Angularインタフェースによって内部的に制御されます。
ControlValueAccessor
is used for creating custom form controls.
ControlValueAccessor
はカスタムフォームコントロールの作成に使用されます。
Two-way binding was popular with forms where you needed to synchronize values from the form fields with the properties of underlying model object.
双方向バインディングは、フォームフィールドの値を基になるモデルオブジェクトのプロパティと同期させる必要があったフォームで一般的でした。
In chapter 7 we’ll cover the use of the NgModel directive in greater detail.
第7章では、NgModel
ディレクティブの使用法について詳しく説明します。
You’ll learn how to handle forms without the need to use
[(ngModel)]
for each form’s control, but there are some cases where it can be handy, so let’s get familiar with the syntax.
フォームのコントロールごとに [(ngModel)]
を使う必要なしにフォームを扱う方法を学びますが、それが便利な場合もあるので、構文に慣れましょう。
Say the landing page of a financial application allows the user to check the latest prices of a stock by entering its symbol in an input field.
金融アプリケーションのリンク先ページで、入力欄に記号を入力して株の最新価格を確認できるとします。
Users often enter the same stocks that they own or follow, such as AAPL for Apple.
ユーザーは、AppleのAAPLなど、自分が所有している株と同じ株を入力することがよくあります。
You could save the last-entered symbol as a cookie (or in HTML5 local storage), and the next time the user opens this page, the program could read the cookie and populate the input field.
最後に入力したシンボルをクッキー(またはHTML5ローカルストレージ)として保存し、次回ユーザーがこのページを開くと、プログラムはCookie
を読み取り、入力フィールドに値を入力できます。
The user should still be able to type in this field, and the entered value should be synchronized with a lastStockSymbol variable, which plays the role of the model.
ユーザーは引き続きこのフィールドに入力する必要があります。入力した値はモデルの役割を果たすlastStockSymbol
変数と同期させる必要があります。
The following code (two-way-binding.ts) implements this functionality.
次のコード(two-way-binding.ts)は、この機能を実装しています。
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'stock-search',
template: `<input type='text' placeholder= "Enter stock symbol"
[(ngModel)] = "lastStockSymbol" /> // (1)
<br>The value of lastStockSymbol is {{lastStockSymbol}}`
})
class StockComponent {
lastStockSymbol: string; // (2)
constructor() {
setTimeout(() => { // (3)
// Code to get the last entered stock from
// local history goes here (not implemented)
this.lastStockSymbol="AAPL";
}, 2000);
}
}
@Component({
selector: 'app',
directives: [StockComponent],
template:`<stock-search></stock-search>`
})
class AppComponent {}
@NgModule({
imports: [ BrowserModule, FormsModule], // (4)
declarations: [ AppComponent],
bootstrap: [ AppComponent ]
})
class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
(1) Requests the two-way binding to synchronize the changes with
lastStockSymbol
.
(1) 変更を lastStockSymbol
と同期するように双方向バインディングを要求します。
(2) The
lastStockSymbol
is the model, and it can be modified either by the user typing in the input field or programmatically.
(2)lastStockSymbol
はモデルであり、ユーザが入力フィールドに入力するか、プログラムによって変更することができます。
(3) To emulate the scenario of reading the last stock symbol from a cookie, we arranged one-second delay after which the value of
lastStockSymbol
will be changed to AAPL and the<input>
field will show it.
(3) 最後の株式シンボルをクッキーから読み込むシナリオをエミュレートするために、lastmostSymbolの値をAAPLに変更し、 <input>
フィールドにそれを示す1秒遅れの遅延を設定しました。
(4) Imports
FormsModule
so we can useNgModel
.
(4) FormsModule
をインポートして、 NgModel
を使うことができます。
The variable and the value of the field lastStockSymbol
<input>
will always be in sync.
フィールドlastmostSymbol <input>
の変数と値は常に同期します。
You can see this in action by running the script in the two-way-binding.ts file.
このスクリプトは、two-way-binding.tsファイルでスクリプトを実行することで実際に動作します。
In the preceding example, we used Angular’s
NgModel
directive to implement two-way data binding, but you can use application-specific properties for this as well.
前述の例では、Angularの NgModel
ディレクティブを使用して双方向データバインディングを実装しましたが、アプリケーション固有のプロパティもこれに使用できます。
You’ll need to name the properties using a special suffix, Change.
プロパティには特別な接尾辞「Change」を使用して名前を付ける必要があります。
In the hands-on section of chapter 6, you’ll see how to modify a product rating using two-way binding with the
[(rating)]
syntax.
第6章の実践的なセクションでは、 [(rating)]
構文で双方向バインディングを使って製品格付けを変更する方法を見ていきます。
In AngularJS, two-way binding was the default mode of operation, which seems like a simple and elegant solution for synchronizing a view and a model.
AngularJSでは、双方向バインディングがデフォルトの操作モードでした。これは、ビューとモデルを同期するためのシンプルで洗練されたソリューションのようです。
But on a complex UI containing dozens of controls, changing the value in one place could cause a chain of binding updates, and performance could suffer.
With two-way binding, debugging could also be more difficult, as there could be many reasons why a particular value was changed.
しかし、数十のコントロールを含む複雑なUIでは、1か所で値を変更すると、一連のバインディング更新が発生し、パフォーマンスが低下する可能性があります。
Was it because of the user’s input or was it the result of a modified value in some variable?
それはユーザーの入力のためか、変数の変更された値の結果ですか?
Implementing change detection inside the Angular framework wasn’t trivial either.
Angularフレームワーク内での変更検出の実装も簡単ではありませんでした。
With a unidirectional data flow, you always know where the change to a particular UI element or component property came from, because there is only one property in the component’s code that could change a particular value on the UI.
単一方向のデータフローでは、UIの特定の値を変更する可能性のあるコンポーネントのコードには1つのプロパティしかないため、特定のUIエレメントまたはコンポーネントプロパティの変更がどこから来たのかが常にわかります。
Reactive programming is about creating responsive (fast) event-driven applications, where an
observable
event stream is pushed to the subscribers. In software engineering,Observer
/Observable
is a well-known pattern, and it’s a good fit in any asynchronous processing scenario.
リアクティブプログラミングとは、応答可能な(高速の)イベントドリブンアプリケーションを作成することです。このアプリケーションでは、オブザーバブル・イベント・ストリームがサブスクライバにプッシュされます。 ソフトウェアエンジニアリングでは、Observer
/Observable
はよく知られているパターンであり、どの非同期処理のシナリオにも適しています。
But reactive programming is a lot more than just an implementation of the
Observer
/Observable
pattern.
しかし、反応型プログラミングは Observer
/Observable
パターンの単なる実装以上のものです。
The
observable
streams can be canceled, they can notify about the end of a stream, and the data pushed to the subscriber can be transformed on the way from the source to the subscriber by applying various operators (functions).
オブザーバブル・ストリームは、取り消すことができ、ストリームの終わりを通知することができ、様々な演算子(関数)を適用することによって、購読者にプッシュされたデータをソースから購読者への途中で変換することができる。
One of the most important characteristics of observables is that they implement the of data processing.
オブザーバブルの最も重要な特性の1つは、オブザーバがデータ処理を実装することです。
push model In contrast, the pull model is implemented by looping through an array, by an Iterable, or by using ES6 generator functions.
プッシュモデルとは対照的に、プルモデルは、配列をループする、Iterableによって、またはES6ジェネレータ関数を使用して実装されます。
Multiple libraries implement reactive extensions that support observable streams, and RxJS (https://github.com/Reactive-Extensions/RxJS) is one such library.
複数のライブラリは、オブザーバブル・ストリームをサポートするリアクティブな拡張機能を実装しており、RxJS( https://github.com/Reactive-Extensions/RxJS )はそのようなライブラリの1つです。
The RxJS library is integrated in Angular.
RxJSライブラリはAngularで統合されています。
The observer is an object that handles a data stream pushed by an observable function.
オブザーバは、オブザーバブル関数によってプッシュされたデータストリームを処理するオブジェクトです。
There are two main types of observables: hot and cold. A cold observable starts streaming data when some code invokes a
subscribe()
function on it.
オブザーバブルには、ホットとコールドの2つの主な種類があります。 コールドオブザーバブルは、コードがsubscribe()
関数を呼び出すときにデータをストリーミングし始めます。
A hot observable streams the data even if there’s no subscriber interested in its data.
ホットオブザーバブルストリームは、データに関心のあるs ubscriber
がいなくてもデータをストリーミングします。
In this book we’ll use only cold observables.
この本では、コールドオブザーバブルのみを利用します。
A script that subscribes to an observable provides the observer object that knows what to do with the stream elements:
オブザーバブルにサブスクライブするスクリプトは、ストリーム要素で何をすべきかを知っているオブザーバオブジェクトを提供します。
let mySubscription: Subscription = someObservable.subscribe(myObserver);
To cancel the stream subscription, invoke the
unsubscribe()
method.
ストリームサブスクリプションをキャンセルするには、unsubscribe()
メソッドを呼び出します。
mySubscription.unsubscribe();
An observable is an object that streams elements from some data source (a socket, an array, UI events) one element at a time.
オブザーバブルとは、あるデータソース(ソケット、配列、UIイベント)の要素を一度に1要素ずつストリーム処理するオブジェクトです。
To be precise, an observable stream knows how to do three things:
正確には、オブザーバブル・ストリームは3つのことを行う方法を知っています:
- Emit the next element (次の要素を放出する)
- Throw an error (エラーを投げる)
- Send a signal that the streaming is over (that the last element has been served) (ストリーミングが終了したことを示す信号を送信する(最後の要素が配信されたことを示す))
Accordingly, an observer object provides up to three callbacks:
したがって、オブザーバオブジェクトは最大3つのコールバックを提供します。
- The function to handle the next element emitted by the observable (オブザーバブルによって生成された次の要素を処理する関数)
- The function to handle errors in the observable (オブザーバブルでエラーを処理する関数)
- The function to be invoked when the stream of data finishes (データのストリームが終了したときに呼び出される関数)
In appendix A we discuss the use of the object, Promise which can invoke an event handler specified in the
then()
function only once.
付録Aでは、then()
関数で指定されたイベントハンドラを1回呼び出すことができるPromiseというオブジェクトの使用について説明します。
The
subscribe()
method is like a sequence ofthen()
invocations: one invocation for each arriving data element.
subscribe()
メソッドは、then()
呼び出しのシーケンスのようなものです。到着するデータ要素ごとに1回呼び出されます。
The application code can apply a sequence of operators, transforming each element prior to supplying it to the handler function.
アプリケーションコードは一連の演算子を適用し、各要素をハンドラ関数に供給する前に変換することができます。
Figure 5.7 shows a sample data flow from an observable that emits data to a subscriber (which implements the observer). In this data flow, we apply two operators:
map()
andfilter()
.
図5.7に、データをサブスクライバ(オブザーバを実装する)に送信するオブザーバブルからのサンプルデータフローを示します。 このデータフローでは、map()
とfilter()
の2つの演算子を適用します。
The emitter (the producer) creates an original stream of data (rectangles).
エミッタ(プロデューサ)は元のデータストリーム(長方形)を作成します。
The map()
operator transfers each rectangle into a triangle, which is given to a filter()
operator that filters out the stream to push only selected triangles to the subscriber.
map()
演算子は、各矩形を三角形に変換します。この三角形は、選択された三角形だけをサブスクライバにプッシュするストリームをフィルタ処理するfilter()
演算子に与えられます。
A more realistic example would be a stream of Customer objects that’s mapped to another stream containing only the property of each customer. The age first stream could be filtered to keep only those customer objects where age < 50.
より現実的な例は、各顧客のプロパティのみを含む別のストリームにマッピングされるCustomerオブジェクトのストリームです。 年齢第一ストリームは、年齢が50歳未満の顧客オブジェクトのみを保持するようにフィルタリングすることができる。
Each operator accepts an observable object as an argument and returns an observable as well.
各演算子は、観測可能なオブジェクトを引数として受け取り、観測可能なものも返します。
This allows for chaining operators.
これにより、演算子の連鎖が可能になります。
The documentation of reactive extensions ( see the ReactiveX documentation for “Operators,” http://reactivex.io/documentation/operators.html ) uses marble diagrams to illustrate operators.
リアクティブエクステンションのドキュメンテーション(ReactiveXドキュメンテーションの "オペレータ" http://reactivex.io/documentation/operators.html参照)は、大理石図を使用して演算子を説明しています。
For example, the
map()
operator is represented as the marble diagram shown in figure 5.8.
たとえば、map()
演算子は、図5.8に示すような大理石図で表されます。
This diagram illustrates a map operator that applies a function multiplying each element of the stream by ten.
この図は、ストリームの各要素に10を掛ける関数を適用するマップ演算子を示しています。
The vertical bars on the right represent the ends of the respective streams.
右の縦のバーは、それぞれのストリームの終わりを表します。
On marble diagrams, errors are represented by red cross signs.
マーブルダイアグラム上では、エラーは赤い十字記号で表されます。
Check out the RxMarbles website (http://rxmarbles.com), which offers interactive marble diagrams for a variety of Rx operators.
RxMarblesウェブサイト( http://rxmarbles.com )をチェックしてください。RxMarblesのウェブサイト( http://rxmarbles.com )には、さまざまなRxオペレータのためのインタラクティブなマーブル・ダイアグラムがあります。
JavaScript has a number of useful methods for working with arrays of data, such as these:
map()
—Allows you to apply a function to each element of the array.
JavaScriptには、以下のようなデータ配列を扱う便利なメソッドがいくつかあります: map()
- 配列の各要素に関数を適用することができます。
With
map()
you can transform one array into another without changing the number of its elements.
map()
を使うと、要素の数を変えずにある配列を別の配列に変換することができます。
For example,
myArray.map(convertToJSON)
.
例えば、 myArray.map(convertToJSON)
のようにします。
filter()
—Allows you to apply a function to each element of an array, filtering out elements by applying some business logic; for example,myArray.filter(priceIsLessThan100)
.
filter()
- 配列の各要素に関数を適用し、ビジネスロジックを適用して要素をフィルタリングすることができます。 たとえば、myArray.filter(priceIsLessThan100)
です。
The resulting array may have fewer elements than the original.
結果の配列は元の要素よりも少ない要素を持つことがあります。
reduce()
—Allows you to produce an aggregate value from an array’s elements; for example,myArray.reduce((x,y) x+y)
.
reduce()
- 配列の要素から集計値を生成することができます。 たとえば、 Array.reduce((x、y)x + y)
などです。
The result of
reduce()
is always a single value.
reduce()
の結果は常に単一の値です。
A stream is a collection of data given to your application over time, and ES6 introduces the concept of iterable and iterators that allow you to treat an array as a data collection and iterate through its elements one at time.
ストリームとは、アプリケーションに与えられたデータの集合です。ES6では、配列をデータコレクションとして扱い、その要素を1つずつ繰り返し処理できるようにするイテレータとイテレータの概念が導入されています。
The source of the iterable data doesn’t have to be an array.
反復可能なデータのソースは配列である必要はありません。
You can write an ES6 generator function (see appendix A) that returns a reference to its iterator, and then you can start pulling the data (one at a time) from this iterator:
myIterator.next().value
.
イテレータへの参照を返すES6ジェネレータ関数(付録Aを参照)を記述すると、このイテレータからデータ(一度に1つ)を引き出すことができます:myIterator.next().value
。
For each value, you can apply some business logic, and then reach out for the next element.
各値に対して、ビジネスロジックを適用して次の要素に手を差し伸べることができます。
An observable object is a more advanced version of an iterator.
オブザーバブル・オブジェクトは、イテレータのより高度なバージョンです。
Iterators use the pull model for retrieving the data, whereas observables push the data to subscribers.
イテレータはプルモデルを使用してデータを取得し、オブザーバブルはデータをサブスクライバにプッシュします。
It’s probably easier to understand the concept of an observable stream by visualizing asynchronous data coming from the server.
サーバーからの非同期データを視覚化することで、オブザーバブル・ストリームの概念を理解するのは簡単でしょう。
We’ll see such an example later in this chapter, and more in chapter 8 while learning how to work with HTTP requests and websockets, but the concept of an observable stream can be applied to events as well.
この章の後半にあるこのような例や、第8章ではHTTPリクエストの処理方法を学び、 オブザーバブル・ストリームの概念をイベントに適用することもできます。
Is an event a one-time deal that just needs a handler function?
イベントはハンドラ関数を必要とするワンタイム取引ですか?
Can you think of an event as a sequence of elements provided over time?
イベントは時間の経過とともに提供される一連の要素として考えることができますか?
We’ll discuss event streams next.
次にイベントストリームについて説明します。
You’ll see how to turn any service into an observable in chapter 8.
Earlier in this chapter, you learned about the syntax of event binding in templates.
この章の前半では、テンプレートのイベント・バインディングの構文について学習しました。
Now let’s take a closer look at the event handling.
では、イベント処理について詳しく見ていきましょう。
Each event is represented by the Event object (or a descendant) containing properties describing the event. Angular applications can handle standard DOM events and can create and emit (dispatch) custom events as well.
各イベントは、イベントを記述するプロパティを含むEventオブジェクト(または子孫)によって表されます。Angularアプリケーションは標準のDOMイベントを処理でき、カスタムイベントも作成して送出できます(ディスパッチ)。
A handler function for an event can be declared with an optional $event parameter that contains a JavaScript object with properties describing the event.
イベントのハンドラ関数は、イベントを記述するプロパティを持つJavaScriptオブジェクトを含むオプションの $event
パラメータで宣言することができます。
With standard DOM events, you can use any functions or properties of the browser’s Event object (see the Mozilla Developer Network documentation for “Event”, http://mzl.la/1EAG6iw).
標準のDOMイベントを使用すると、ブラウザのEventオブジェクトの任意の関数またはプロパティを使用できます(Mozilla Developer NetworkドキュメントのEvent参照、http://mzl.la/1EAG6iw )。
In some cases, you won’t be interested in reading the event object’s properties, such as when the only button on a page is clicked, and this is all that matters.
場合によっては、ページ上の唯一のボタンがクリックされたときなど、イベントオブジェクトのプロパティを読み込むことに興味を持たない場合もあります。
In other cases, you may want to know specific information, such as what character was entered in the
<input>
field when the keyup event was dispatched:
他のケースでは、keyupイベントが送出されたときに <input>
フィールドにどの文字が入力されたかなどの特定の情報を知りたい場合があります:
template:`<input (keyup)="onKey($event)">`
...
onKey(event:any) {
console.log("You have entered " + event.target.value);
}
The preceding code snippet accesses the value property of the
<input>
element by using event.
前のコードスニペットは、eventを使用して <input>
要素のvalueプロパティにアクセスします。
target, which points at the element that dispatched the event.
target:イベントをディスパッチした要素をポイントします。
But Angular allows you to get ahold of the HTML element (and its properties) right inside the template by declaring a template local variable that will always hold a reference to its HTML element.
しかし、Angularでは、HTMLエレメントへの参照を常に保持するテンプレートローカル変数を宣言することによって、テンプレート内でHTMLエレメント(およびそのプロパティ)を取得することができます。
The following code fragment declares a mySearchField local template variable (the name must start with a hash sign), extracts the value of the hosting HTML element (
<input>
in this case), and passes it to the event handler function rather than the reference to the Event object.
次のコードでは、mySearchFieldローカルテンプレート変数(名前はハッシュ記号で始まる必要があります)を宣言し、ホストするHTML要素の値を抽出して(この場合は<input>
)、イベントハンドラ関数に渡します Eventオブジェクトへの参照
Note that the hash sign is needed only to declare a local variable in the template; you don’t need the hash when using this variable in the JavaScript portion of the code:
ハッシュ記号は、テンプレート内のローカル変数を宣言するためにのみ必要であることに注意してください。 この変数をコードのJavaScript部分で使用する場合、ハッシュは必要ありません。
template:`<input #mySearchField (keyup)="onKey(mySearchField.value)">`
...
onKey(value: string) {
console.log("You have entered " + value);
}
If your code dispatches a custom event, it can carry application-specific data, and the event object can be strongly typed (not just be of the type any).
You’ll see how to do this in chapter 6, in the section titled “Output properties and custom events.”
A traditional JavaScript application treats a dispatched event as a one-time deal; for example, one click results in one function invocation. Angular offers another approach where you consider events as observable streams of data happening over time.
従来のJavaScriptアプリケーションは、ディスパッチされたイベントを1回限りの処理として扱います。 たとえば、1回クリックすると1回の関数呼び出しが行われます。 Angularは、イベントをオブザーバブル・ストリームのストリームとみなす別のアプローチを提供します。
Handling observable streams is an important technique to master, so let’s see what it’s all about.
オブザーバブル・ストリームを扱うことは習得する重要な技法なので、それが何であるかを見てみましょう。
By subscribing to a stream, your code expresses an interest in receiving the stream’s elements. During subscription, you specify the code to be invoked when the next element is emitted, and optionally the code for error processing and stream completion.
ストリームに登録することで、コードはストリームの要素を受け取ることに関心を示します。 サブスクリプション時に、次の要素が発行されたときに呼び出されるコードを指定します。オプションで、エラー処理とストリームの完了コードも指定できます。
Often you’ll specify a number of chained operators and then invoke the
subscribe()
method.
多くの場合、チェーン演算子の数を指定し、次にsubscribe()
メソッドを呼び出します。
How does all this apply to events coming from the UI? You could use event binding that handles multiple keyup events and handles the value of
lastStockSymbol
:
これはUIからのイベントにどのように適用されますか? 複数のキーアップイベントを処理し、lastStockSymbol
の値を処理するイベントバインディングを使用できます。
<input type='text' (keyup) = "getStockPrice($event)">
Isn’t this technique good enough for handling multiple events? Imagine that the preceding code is used to get a price quote for the AAPL stock.
このテクニックは、複数のイベントを処理するのに十分ですか? 前のコードがAAPL株の価格見積もりを取得するために使用されるとします。
After the user types the first A, the
getStockPrice()
function will make a Promise-based request to the server, which will return the price of A, if there is such a stock.
ユーザーが最初のAをタイプした後、 getStockPrice()
関数はサーバーにPromiseベースの要求を行い、そのような在庫があればAの価格を返します。
Then the user enters the second A, which results in another server request for the AA price quote. The process repeats for AAP and AAPL.
次に、ユーザーは2番目のAを入力します。これにより、AA価格見積もりの別のサーバー要求が行われます。 このプロセスは、AAPおよびAAPLに対して繰り返されます。
This isn’t what we want, and we can arrange a 500 millisecond delay so the user can have enough time to type several letters. The
setTimeout()
function comes to the rescue!
これは私たちが望むものではなく、ユーザーが複数の文字を入力するのに十分な時間を持つように500ミリ秒の遅延を調整することができます。 setTimeout()
関数が救助に来ます!
What if the user types slowly, and during the 500 millisecond interval manages only to enter AAP? The first request for AAP goes to the server, and 500 milliseconds later the second request for AAPL is sent.
ユーザーがゆっくり入力し、500ミリ秒の間隔でAAPに入るだけの場合はどうなりますか? AAPの最初の要求はサーバーに送られ、500ミリ秒後に2回目のAAPL要求が送信されます。
A program can’t cancel the first HTTP request if the server returns a Promise, so we’ll just keep our fingers crossed that our users type quickly and don’t overload the server with unwanted requests.
サーバーがプロミスを返す場合、プログラムは最初のHTTPリクエストをキャンセルできません。そのため、ユーザーがすぐに入力し、不要なリクエストでサーバーを過負荷にしないようにしています。
With observable streams, there’s a better solution to this problem, and some of the Angular UI components can generate them. For example, the FormControl class is one of the fundamental blocks of forms processing that represents form elements.
オブザーバブル・ストリームでは、この問題に対するより良い解決策があり、Angular UIコンポーネントの中には、それらを生成できるものがあります。たとえば、FormControlクラスは、フォーム要素を表すフォーム処理の基本ブロックの1つです。
Each form element has its own FormControl object. By default, whenever the value of the form element changes,
FormControl
emits thevalueChanges
event, which produces an observable stream you can subscribe to.
各フォーム要素には独自のFormControlオブジェクトがあります。デフォルトでは、フォームの値要素が変更されると、FormControl
はvalueChanges
イベントを発行し、それはサブスクライブ可能な観測可能なストリームを生成します。
Let’s write a small app that uses a simple form with one input field that generates an observable stream.
オブザーバブル・ストリームを生成する1つの入力フィールドを持つ単純なフォームを使用する小さなアプリケーションを作成しましょう。
To understand the next example, you just need to know that form elements are bound to Angular component properties via the formControl attribute.
次の例を理解するには、form要素がformControl属性を使用してAngularコンポーネントのプロパティにバインドされていることを知りたいだけです。
There’s a way to program forms just by using directives in the component’s template.
コンポーネントのテンプレート内のディレクティブを使用するだけでフォームをプログラミングする方法があります。
These are template-driven forms. You can also program forms by creating form-related objects in the TypeScript code of your components.
これらはテンプレート駆動型です。 また、コンポーネントのTypeScriptコードにフォーム関連のオブジェクトを作成して、フォームをプログラムすることもできます。
These are reactive forms. We’ll cover Angular forms in chapter 7.
これらは反応型である。 Angularフォームについては、第7章で説明します。
The following code sample (observable-events.ts) applies just one operator,
debounceTime()
, prior to invokingsubscribe()
. RxJS supports dozens of operators that you can use with Observable streams ( see the RxJS documentation, http://bit.ly/1SuZzul ), but Angular didn’t reimplement all of them inside the framework.
次のコードサンプル(observable-events.ts)は、subscribe()
を呼び出す前に演算子 debounceTime()
を1つだけ適用します。 RxJSは、オブザーバブル・ストリームで使用できる数十の演算子をサポートしています( RxJSのマニュアル、 http://bit.ly/1SuZzul )、Angularはフレームワーク内でそれらのすべてを再実装しませんでした。
That’s why we need to import additional operators from RxJS, which is a peer dependency of Angular. The
debounceTime()
operator allows us to specify a delay in emitting data elements of a stream.
そのため、Angularのピア依存関係であるRxJSから追加の演算子をインポートする必要があります。 debounceTime()
演算子を使用すると、ストリームのデータ要素を送出する際の遅延を指定できます。
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormControl, ReactiveFormsModule} from '@angular/forms';
//import 'rxjs/Rx'; // import all operators
import 'rxjs/add/operator/debounceTime';
@Component({
selector: "app",
template: `
<h2>Observable events demo</h2>
<input type="text" placeholder="Enter stock" [formControl]="searchInput">
`
})
class AppComponent {
searchInput: FormControl = new FormControl('');
constructor(){
this.searchInput.valueChanges
.debounceTime(500)
.subscribe(stock => this.getStockQuoteFromServer(stock));
}
getStockQuoteFromServer(stock: string) {
console.log(`The price of ${stock} is ${100*Math.random().toFixed(4)}`);
}
}
@NgModule({
imports: [ BrowserModule, ReactiveFormsModule],
declarations: [ AppComponent],
bootstrap: [ AppComponent ]
})
class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
You can either import the implementation of specific operators as here, or import all of them using
import 'rxjs/Rx'
;.
ここでは特定の演算子の実装をインポートするか、 import 'rxjs / Rx'
;を使ってそれらのすべてをインポートすることができます。
This
<input>
element is represented by the ngFormControl named search.
この<input>
要素は、ngFormControl
という名前のsearchで表されます。
Waits 500 milliseconds before emitting the next event with the content of the
<input>
element.
<input>
要素の内容で次のイベントを発行するまで500ミリ秒待ちます。
Subscribes to the observable stream. Imports the module supporting reactive forms.
オブザーバブル・ストリームを購読します。反応形式をサポートするモジュールをインポートします。
The method will create the instance of
subscribe()
the Observer, which in our example will pass each next value from the stream generated by the searchInput to thegetStockQuoteFromServer()
method.
メソッドはObserverのsubscribe()インスタンスを作成します。この例では、searchInputによって生成されたストリームから次の各値を getStockQuoteFromServer()
メソッドに渡します。
In a real-world scenario, this method would issue a request to the server, and you’ll see such an app in the next section, but for now this function just generates a random number.
現実のシナリオでは、このメソッドはサーバーにリクエストを発行し、次のセクションでそのようなアプリケーションを表示しますが、今のところこの関数は乱数を生成します。
If we didn’t use the
debounceTime()
operator, the valueChanges event would be emitted after each character typed by the user.
debounceTime()
演算子を使用しなかった場合、valueChangesイベントは、ユーザーが入力した各文字の後に出力されます。
To prevent processing each keystroke, we instruct searchInput to emit the data with a 500 millisecond delay, which allows the user to enter several characters before the content of the input field is emitted into the stream.
各キーストロークの処理を防ぐため、searchInputに500ミリ秒の遅延でデータを出力するよう指示します。入力フィールドの内容がストリームに出力される前にユーザーが複数の文字を入力できるようにします。
No matter how many operators you chain together, none of them will be invoked on the stream until you invoke
subscribe()
.
連鎖している演算子の数にかかわらず、subscribe()
を呼び出すまで、それらのどれもがストリーム上で呼び出されません。
Figure 5.9 shows a screenshot taken after we started the preceding application and entered AAPL in the input field.
図5.9に、前のアプリケーションを開始して入力フィールドにAAPLを入力した後のスクリーンショットを示します。
In the previous code sample, we handled an observable stream that the object provided for us when the DOM FormControl object emitted the change event.
前のコードサンプルでは、DOM FormControl
オブジェクトがchangeイベントを発行したときにオブジェクトが提供したオブザーバブル・ストリームを処理しました。
If you prefer to generate an observable stream based on another event (such as on keyup), you can use the RxJS
Observable.fromEvent()
API ( see the RxJS documentation on GitHub, http://bit.ly/1SkT7WL ).
他のイベント(キーアップなど)に基づいてオブザーバブル・ストリームを生成したい場合は、RxJS Observable.fromEvent()
APIを使用できます(GitHubのRxJSドキュメント、http://bit.ly/1SkT7WL を参照)。
You may argue that you could have implemented the preceding example by simply handling the input event, which would be dispatched when the user finished entering the stock symbol and moved the focus out of the input field.
前述の例は、入力イベントを処理するだけで実装できると主張するかもしれません。これは、ユーザが株式シンボルの入力を完了し、入力フィールドからフォーカスを移動したときに送出されます。
This is true, but there are many scenarios where you’ll want an immediate response from the server, such as retrieving and filtering a data collection as the user types.
これは当てはまりますが、ユーザーが入力するデータコレクションの取得やフィルタリングなど、サーバーからの即時の応答が必要なシナリオが数多くあります。
The preceding example doesn’t actually make any network requests to the server for price quotes—we simply generate random numbers on the user’s computer.
上記の例では、実際にサーバーにネットワークでの価格見積もりを要求していません。ユーザーのコンピュータで乱数を生成するだけです。
Even if the user enters a wrong stock symbol, this example will result in a local invocation of
Math.random()
, which has a negligible effect on the application’s performance.
ユーザーが間違った株式シンボルを入力したとしても、この例では Math.random()
のローカル呼び出しが行われ、アプリケーションのパフォーマンスにはほとんど影響しません。
In a real-world application, the user’s typos may generate network requests that introduce delays while returning quotes for mistakenly entered stock symbols. In the next section we’ll show you how to cancel pending server requests with observable streams.
実際のアプリケーションでは、誤って入力された株式記号の引用符を返す間に遅延を招くネットワーク要求がユーザーの誤植によって生成されることがあります。 次のセクションでは、オブザーバブル・ストリームで保留中のサーバー要求を取り消す方法を説明します。
One of the benefits of observables over promises is that the former can be canceled.
オブザーバブルがプロミスを超えるメリットの1つは、キャンセルできることです。
In the previous section we offered one scenario in which a typo might result in useless server requests. Implementing master-detail views is another use case for a request cancellation.
前のセクションでは、タイプミスがサーバー要求を無駄にするシナリオを示しました。 マスター詳細ビューの実装は、要求の取り消しのもう1つの使用例です。
Say a user clicks on a row in a list of products to see the product details that must be retrieved from the server. Then they change their mind and click on another row, which will issue another server request, and the pending request should ideally be canceled.
ユーザーが製品リスト内の行をクリックすると、サーバーから取得する必要がある製品の詳細が表示されます。 その後、彼らは心を変えて別の行をクリックすると、別のサーバー要求が発行され、保留中の要求は理想的に取り消されます。
Let’s look at how you can cancel pending requests by creating an application that will issue HTTP requests as the user types in the input field. Now we’ll handle two observable streams:
ユーザーが入力フィールドに入力したときにHTTP要求を発行するアプリケーションを作成して、保留中の要求を取り消す方法を見てみましょう。 今度は観測可能な2つのストリームを扱います:
- The observable stream produced by the search field (検索フィールドによって生成されたオブザーバブル・ストリーム)
- The observable stream produced by the HTTP requests issued while the user is typing in the search field (ユーザーが検索フィールドに入力している間に発行されたHTTPリクエストによって生成されたオブザーバブル・ストリーム)
For this example (observable-events-http.ts) we’ll use the free weather service at http://openweathermap.org, which provides an API for making weather requests for cities around the world.
この例(observable-events-http.ts)では、世界中の都市の気象要求を作成するためのAPIを提供する http://openweathermap.org の無料気象サービスを使用します。
It returns the weather information as a JSON-formatted string.
天気情報をJSON形式の文字列として返します。
For example, to get the current temperature in London in Fahrenheit (units=imperial) the URL would look like this:
たとえば、ロンドンの現在の気温(華氏)を取得するには、URLは次のようになります。
http://api.openweathermap.org/data/2.5/find?q=London&units=imperial&appid=12345
To use this service, we went to openweathermap.org and received from them an application ID (appid). The following example constructs the request URL by concatenating the base URL with the entered city name and the application ID.
このサービスを利用するために、私たちはopenweathermap.orgに行き、アプリケーションID(appid)を受け取った。 次の例では、ベースURLと入力された都市名およびアプリケーションIDを連結してリクエストURLを作成します。
As the user enters the characters of the city name, the code subscribes to the event stream and issues HTTP requests. If a new request is issued before the response from the previous one comes back, the
switchMap()
operator cancels the previous request and sends the new one to this weather service. Canceling pending requests can’t be done with promises.
ユーザーが都市名の文字を入力すると、コードはイベントストリームにサブスクライブし、HTTP要求を発行します。 前のリクエストからの応答が返る前に新しいリクエストが発行された場合、 switchMap()
演算子は前のリクエストをキャンセルし、新しいリクエストをこの気象サービスに送ります。 保留中のリクエストをキャンセルすることはプロミスではできません。
This example also uses the FormControl directive to generate an observable stream from the input field where the user enters the name of the city.
この例では、FormControl
ディレクティブを使用して、ユーザーが都市の名前を入力する入力フィールドからオブザーバブル・ストリームを生成します。
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule, Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormControl, ReactiveFormsModule} from '@angular/forms';
import {HttpModule, Http} from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
@Component({
selector: "app",
template: `
<h2>Observable weather</h2>
<input type="text" placeholder="Enter city" [formControl]="searchInput">
<h3>{{temperature}}</h3>
`
})
class AppComponent {
private baseWeatherURL: string= 'http://api.openweathermap.org/data/2.5/find?q=';
private urlSuffix: string = "&units=imperial&appid=ca3f6d6ca3973a518834983d0b318f73";
searchInput: FormControl = new FormControl('');
temperature: string;
constructor(private http:Http){
this.searchInput.valueChanges
.debounceTime(200)
.switchMap(city => this.getWeather(city))
.subscribe(
res => {
if (res['cod'] === '404') return;
if (!res.main) {
this.temperature ='City is not found';
} else {
this.temperature = `Current temperature is ${res.main.temp}F, ` + `humidity: ${res.main.humidity}%`;
}
},
err => console.log(`Can't get weather. Error code: %s, URL: %s`, err.message, err.url),
() => console.log(`Weather is retrieved`)
);
}
getWeather(city: string): Observable<Array<string>> {
return this.http.get(this.baseWeatherURL + city + this.urlSuffix)
.map(res => {
console.log(res);
return res.json()
});
}
}
@NgModule({
imports: [ BrowserModule, ReactiveFormsModule, HttpModule],
declarations: [ AppComponent],
bootstrap: [ AppComponent ]
})
class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);