填寫這份《一分鐘調查》,幫我們(開發組)做得更好!去填寫Home

範本變數

Template variables

範本變數可以幫助你在範本的另一部分使用這個部分的資料。使用範本變數,你可以執行某些任務,比如響應使用者輸入或微調應用的表單。

Template variables help you use data from one part of a template in another part of the template. With template variables, you can perform tasks such as respond to user input or finely tune your application's forms.

範本變數可以參考這些東西:

A template variable can refer to the following:

本章包含程式碼片段的工作實例參閱現場演練 / 下載範例

See the現場演練 / 下載範例for a working example containing the code snippets in this guide.

語法

Syntax

在範本中,要使用井號 # 來宣告一個範本變數。下列範本變數 #phone 語法在 <input> 元素上聲明瞭一個名為 phone 的變數

In the template, you use the hash symbol, #, to declare a template variable. The following template variable, #phone, declares a phone variable on an <input> element.

<input #phone placeholder="phone number" />
src/app/app.component.html
      
      <input #phone placeholder="phone number" />
    

你可以在元件範本中的任何地方參考某個範本變數。這裡的 <button> 就參考了 phone 變數。

You can refer to a template variable anywhere in the component's template. Here, a <button> further down the template refers to the phone variable.

<input #phone placeholder="phone number" /> <!-- lots of other elements --> <!-- phone refers to the input element; pass its `value` to an event handler --> <button (click)="callPhone(phone.value)">Call</button>
src/app/app.component.html
      
      <input #phone placeholder="phone number" />

<!-- lots of other elements -->

<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
    

Angular 是如何為範本變數賦值的

How Angular assigns values to template variables

Angular 根據你所宣告的變數的位置給範本變數賦值:

Angular assigns a template variable a value based on where you declare the variable:

  • 如果在元件上宣告變數,該變數就會參考該元件實例。

    If you declare the variable on a component, the variable refers to the component instance.

  • 如果在標準的 HTML 標記上宣告變數,該變數就會參考該元素。

    If you declare the variable on a standard HTML tag, the variable refers to the element.

  • 如果你在 <ng-template> 元素上宣告變數,該變數就會參考一個 TemplateRef 實例來代表此範本。關於 <ng-template> 的更多資訊,請參閱結構型指令 中的 ng-template 部分。

    If you declare the variable on an <ng-template> element, the variable refers to a TemplateRef instance, which represents the template. For more information on <ng-template>, see the ng-template section of Structural directives.

  • 如果該變數在右側指定了一個名字,比如 #var="ngModel" ,那麼該變數就會參考所在元素上具有這個 exportAs 名字的指令或元件。

    If the variable specifies a name on the right-hand side, such as #var="ngModel", the variable refers to the directive or component on the element with a matching exportAs name.

NgForm 與範本變數一起使用

Using NgForm with template variables

在大多數情況下,Angular 會把範本變數的值設定為它所在的元素。在前面的例子中, phone 參考的是電話號碼 <input> 。該按鈕的 click 處理程式會把這個 <input> 的值傳給該元件的 callPhone() 方法。

In most cases, Angular sets the template variable's value to the element on which it occurs. In the previous example, phone refers to the phone number <input>. The button's click handler passes the <input> value to the component's callPhone() method.

這裡的 NgForm 指令示範瞭如何透過參考指令的的 exportAs 名字來參考不同的值。在下面的例子中,範本變數 itemForm 在 HTML 中分別出現了三次。

The NgForm directive demonstrates getting a reference to a different value by reference a directive's exportAs name. In the following example, the template variable, itemForm, appears three times separated by HTML.

<form #itemForm="ngForm" (ngSubmit)="onSubmit(itemForm)"> <label for="name">Name <input class="form-control" name="name" ngModel required /> </label> <button type="submit">Submit</button> </form> <div [hidden]="!itemForm.form.valid"> <p>{{ submitMessage }}</p> </div>
src/app/hero-form.component.html
      
      <form #itemForm="ngForm" (ngSubmit)="onSubmit(itemForm)">
  <label for="name">Name <input class="form-control" name="name" ngModel required />
  </label>
  <button type="submit">Submit</button>
</form>

<div [hidden]="!itemForm.form.valid">
  <p>{{ submitMessage }}</p>
</div>
    

如果沒有 ngForm 這個屬性值,itemForm 參考的值將是 HTMLFormElement 也就是 <form> 元素。而 ComponentDirective 之間的差異在於 Angular 在沒有指定屬性值的情況下,Angular 會參考 Component,而 Directive 不會改變這種隱式參考(即它的宿主元素)。

Without the ngForm attribute value, the reference value of itemForm would be the HTMLFormElement, <form>. There is, however, a difference between a Component and a Directive in that Angular references a Component without specifying the attribute value, and a Directive does not change the implicit reference, or the element.

而使用了 NgForm 之後,itemForm 就是對 NgForm 指令的參考,可以用它來追蹤表單中每一個控制元件的值和有效性。

With NgForm, itemForm is a reference to the NgForm directive with the ability to track the value and validity of every control in the form.

與原生的 <form> 元素不同, NgForm 指令有一個 form 屬性。如果 itemForm.form.valid 無效,那麼 NgFormform 屬性就會讓你禁用提交按鈕。

Unlike the native <form> element, the NgForm directive has a form property. The NgForm form property allows you to disable the submit button if the itemForm.form.valid is invalid.

範本變數的作用域

Template variable scope

你可以在包含此範本變數的範本中的任何地方參考它。而 結構型指令(如 *ngIf*ngFor<ng-template> 同樣充當了範本的邊界。你不能在這些邊界之外訪問其中的範本變數。

You can refer to a template variable anywhere within its surrounding template. Structural directives, such as *ngIf and *ngFor, or <ng-template> act as a template boundary. You cannot access template variables outside of these boundaries.

同名變數在範本中只能定義一次,這樣執行時它的值就是可預測的。

Define a variable only once in the template so the runtime value remains predictable.

在巢狀範本中訪問

Accessing in a nested template

內部範本可以訪問外範本定義的範本變數。

An inner template can access template variables that the outer template defines.

在下面的例子中,修改 <input> 中的文字值也會改變 <span> 中的值,因為 Angular 會立即透過範本變數 ref1 來更新這種變化。

In the following example, changing the text in the <input> changes the value in the <span> because Angular immediately updates changes through the template variable, ref1.

<input #ref1 type="text" [(ngModel)]="firstExample" /> <span *ngIf="true">Value: {{ ref1.value }}</span>
src/app/app.component.html
      
      <input #ref1 type="text" [(ngModel)]="firstExample" />
<span *ngIf="true">Value: {{ ref1.value }}</span>
    

在這種情況下,有一個包含這個 <span> 的隱式 <ng-template>,而該變數的定義在該隱式範本之外。訪問父範本中的範本變數是可行的,因為子範本會從父範本繼承上下文。

In this case, there is an implied <ng-template> around the <span> and the definition of the variable is outside of it. Accessing a template variable from the parent template works because the child template inherits the context from the parent template.

我們用更囉嗦的形式重寫上述的程式碼,可以明確地顯示出 <ng-template>

Rewriting the above code in a more verbose form explicitly shows the <ng-template>.

<input #ref1 type="text" [(ngModel)]="firstExample" /> <!-- New template --> <ng-template [ngIf]="true"> <!-- Since the context is inherited, the value is available to the new template --> <span>Value: {{ ref1.value }}</span> </ng-template>
      
      <input #ref1 type="text" [(ngModel)]="firstExample" />

<!-- New template -->
<ng-template [ngIf]="true">
  <!-- Since the context is inherited, the value is available to the new template -->
  <span>Value: {{ ref1.value }}</span>
</ng-template>
    

但是,從外部的父範本訪問本範本中的變數是行不通的。

However, accessing a template variable from outside the parent template doesn't work.

<input *ngIf="true" #ref2 type="text" [(ngModel)]="secondExample" /> <span>Value: {{ ref2?.value }}</span> <!-- doesn't work -->
      
      <input *ngIf="true" #ref2 type="text" [(ngModel)]="secondExample" />
<span>Value: {{ ref2?.value }}</span> <!-- doesn't work -->
    

這個更囉嗦的形式表明 ref2 位於外部的父範本中。

The verbose form shows that ref2 is outside the parent template.

<ng-template [ngIf]="true"> <!-- The reference is defined within a template --> <input #ref2 type="text" [(ngModel)]="secondExample" /> </ng-template> <!-- ref2 accessed from outside that template doesn't work --> <span>Value: {{ ref2?.value }}</span>
      
      <ng-template [ngIf]="true">
  <!-- The reference is defined within a template -->
  <input #ref2 type="text" [(ngModel)]="secondExample" />
</ng-template>
<!-- ref2 accessed from outside that template doesn't work -->
<span>Value: {{ ref2?.value }}</span>
    

考慮下面這個帶 *ngFor 的使用範例。

Consider the following example that uses *ngFor.

<ng-container *ngFor="let i of [1,2]"> <input #ref type="text" [value]="i" /> </ng-container> {{ ref.value }}
      
      <ng-container *ngFor="let i of [1,2]">
  <input #ref type="text" [value]="i" />
</ng-container>
{{ ref.value }}
    

這裡,ref.value 不起作用。結構型指令 *ngFor 將範本實例化了兩次,因為 *ngFor 在對陣列中的兩個條目進行迭代。因此不可能定義出 ref.value 指向的是誰。

Here, ref.value doesn't work. The structural directive, *ngFor instantiates the template twice because *ngFor iterates over the two items in the array. It is impossible to define what the ref.value reference signifies.

對於結構型指令,比如 *ngFor*ngIf ,Angular 也無法知道範本是否曾被實例化過。

With structural directives, such as *ngFor or *ngIf, there is no way for Angular to know if a template is ever instantiated.

結果,Angular 無法訪問該值並返回錯誤。

As a result, Angular isn't able to access the value and returns an error.

訪問 <ng-template> 的範本變數

Accessing a template variable within <ng-template>

<ng-template> 上宣告變數時,該變數會參考一個 TemplateRef 實例來表示該範本。

When you declare the variable on an <ng-template>, the variable refers to a TemplateRef instance, which represents the template.

<ng-template #ref3></ng-template> <button (click)="log(ref3)">Log type of #ref</button>
src/app/app.component.html
      
      <ng-template #ref3></ng-template>
<button (click)="log(ref3)">Log type of #ref</button>
    

在這個例子中,單擊該按鈕會呼叫 log() 函式,它把 #ref3 的值輸出到控制檯。因為 #ref 變數在 <ng-template> 上,所以它的值是一個 TemplateRef

In this example, clicking the button calls the log() function, which outputs the value of #ref3 to the console. Because the #ref variable is on an <ng-template>, the value is TemplateRef.

下面是一個名為 TemplateRefTemplateRef() 函式在瀏覽器控制檯中展開時的輸出。

The following is the expanded browser console output of the TemplateRef() function with the name of TemplateRef.

▼ ƒ TemplateRef() name: "TemplateRef" __proto__: Function
      
       ƒ TemplateRef()
name: "TemplateRef"
__proto__: Function