parent
2c2135d331
commit
e2fd628618
@ -0,0 +1,62 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
import { logging } from 'selenium-webdriver';
|
||||||
|
|
||||||
|
describe('Template-reference-variables-example', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.get('');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// helper function used to test what's logged to the console
|
||||||
|
async function logChecker(button, contents) {
|
||||||
|
const logs = await browser
|
||||||
|
.manage()
|
||||||
|
.logs()
|
||||||
|
.get(logging.Type.BROWSER);
|
||||||
|
const message = logs.filter(({ message }) =>
|
||||||
|
message.indexOf(contents) !== -1 ? true : false
|
||||||
|
);
|
||||||
|
expect(message.length).toBeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should display Template reference variables', function() {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual(
|
||||||
|
'Template reference variables'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log a Calling 123 ... message', async () => {
|
||||||
|
let callButton = element.all(by.css('button')).get(0);
|
||||||
|
let phoneInput = element.all(by.css('input')).get(0);
|
||||||
|
await phoneInput.sendKeys('123');
|
||||||
|
await callButton.click();
|
||||||
|
const contents = 'Calling 123 ...';
|
||||||
|
await logChecker(callButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log a Faxing 123 ... message', async () => {
|
||||||
|
let faxButton = element.all(by.css('button')).get(1);
|
||||||
|
let faxInput = element.all(by.css('input')).get(1);
|
||||||
|
await faxInput.sendKeys('123');
|
||||||
|
await faxButton.click();
|
||||||
|
const contents = 'Faxing 123 ...';
|
||||||
|
await logChecker(faxButton, contents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display a disabled button', function() {
|
||||||
|
let disabledButton = element.all(by.css('button')).get(2);
|
||||||
|
expect(disabledButton.isEnabled()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should submit form', async () => {
|
||||||
|
let submitButton = element.all(by.css('button')).get(3);
|
||||||
|
let nameInput = element.all(by.css('input')).get(2);
|
||||||
|
await nameInput.sendKeys('123');
|
||||||
|
await submitButton.click();
|
||||||
|
expect(element.all(by.css('div > p')).get(2).getText()).toEqual('Submitted. Form value is {"name":"123"}');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,55 @@
|
|||||||
|
<h1>Template reference variables</h1>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2>Pass value to an event handler</h2>
|
||||||
|
<p>See console for output.</p>
|
||||||
|
<!-- #docregion ref-phone -->
|
||||||
|
<!-- #docregion ref-var -->
|
||||||
|
<input #phone placeholder="phone number" />
|
||||||
|
<!-- #enddocregion ref-var -->
|
||||||
|
|
||||||
|
<!-- lots of other elements -->
|
||||||
|
|
||||||
|
<!-- phone refers to the input element; pass its `value` to an event handler -->
|
||||||
|
<button (click)="callPhone(phone.value)">Call</button>
|
||||||
|
<!-- #enddocregion ref-phone -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<!-- #docregion ref-fax -->
|
||||||
|
<input ref-fax placeholder="fax number" />
|
||||||
|
<button (click)="callFax(fax.value)">Fax</button>
|
||||||
|
<!-- #enddocregion ref-fax -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2>Template reference variable with disabled button</h2>
|
||||||
|
<p>btn refers to the button element.</p>
|
||||||
|
<button
|
||||||
|
#btn
|
||||||
|
disabled
|
||||||
|
[innerHTML]="'disabled by attribute: ' + btn.disabled"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h2>Reference variables, forms, and NgForm</h2>
|
||||||
|
<!-- #docregion ngForm -->
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<!-- #enddocregion ngForm -->
|
||||||
|
|
||||||
|
|
||||||
|
<p>JSON: {{ itemForm.form.value | json }}</p>
|
@ -0,0 +1,27 @@
|
|||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
it(`should have as title 'app'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app.title).toEqual('app');
|
||||||
|
}));
|
||||||
|
it('should render title in a h1 tag', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||||
|
}));
|
||||||
|
});
|
@ -0,0 +1,31 @@
|
|||||||
|
import { Component, ViewChild } from '@angular/core';
|
||||||
|
import { NgForm } from '@angular/forms';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
@ViewChild('itemForm', { static: false }) form: NgForm;
|
||||||
|
|
||||||
|
private _submitMessage = '';
|
||||||
|
|
||||||
|
get submitMessage() {
|
||||||
|
return this._submitMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form: NgForm) {
|
||||||
|
this._submitMessage = 'Submitted. Form value is ' + JSON.stringify(form.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
callPhone(value: string) {
|
||||||
|
console.warn(`Calling ${value} ...`);
|
||||||
|
}
|
||||||
|
|
||||||
|
callFax(value: string) {
|
||||||
|
console.warn(`Faxing ${value} ...`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
FormsModule
|
||||||
|
],
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Template Reference Variables Example</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root>Loading...</app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,11 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"description": "Template Reference Variables",
|
||||||
|
"files": ["!**/*.d.ts", "!**/*.js", "!**/*.[1,2].*"],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Template Reference Variables"]
|
||||||
|
}
|
@ -1686,70 +1686,73 @@ For example, you could replace the `<app-best-item>` switch case with the follow
|
|||||||
|
|
||||||
{@a template-reference-variable}
|
{@a template-reference-variable}
|
||||||
|
|
||||||
|
{@a template-reference-variables--var-}
|
||||||
|
|
||||||
{@a ref-vars}
|
{@a ref-vars}
|
||||||
|
|
||||||
{@a ref-var}
|
{@a ref-var}
|
||||||
|
|
||||||
## Template reference variables ( <span class="syntax">#var</span> )
|
## Template reference variables (`#var`)
|
||||||
|
|
||||||
A **template reference variable** is often a reference to a DOM element within a template.
|
A **template reference variable** is often a reference to a DOM element within a template.
|
||||||
It can also be a reference to an Angular component or directive or a
|
It can also refer to a directive (which contains a component), an element, [TemplateRef](api/core/TemplateRef), or a <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" title="MDN: Web Components">web component</a>.
|
||||||
<a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" title="MDN: Web Components">web component</a>.
|
|
||||||
|
For a demonstration of the syntax and code snippets in this section, see the <live-example name="template-reference-variables">template reference variables example</live-example>.
|
||||||
|
|
||||||
|
|
||||||
Use the hash symbol (#) to declare a reference variable.
|
Use the hash symbol (#) to declare a reference variable.
|
||||||
The `#phone` declares a `phone` variable on an `<input>` element.
|
The following reference variable, `#phone`, declares a `phone` variable on an `<input>` element.
|
||||||
|
|
||||||
<code-example path="template-syntax/src/app/app.component.html" region="ref-var" header="src/app/app.component.html" linenums="false">
|
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-var" header="src/app/app.component.html" linenums="false">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
You can refer to a template reference variable _anywhere_ in the template.
|
You can refer to a template reference variable anywhere in the component's template.
|
||||||
The `phone` variable declared on this `<input>` is
|
Here, a `<button>` further down the template refers to the `phone` variable.
|
||||||
consumed in a `<button>` on the other side of the template
|
|
||||||
|
|
||||||
<code-example path="template-syntax/src/app/app.component.html" region="ref-phone" header="src/app/app.component.html" linenums="false">
|
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-phone" header="src/app/app.component.html" linenums="false">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
<h3 class="no-toc">How a reference variable gets its value</h3>
|
<h3 class="no-toc">How a reference variable gets its value</h3>
|
||||||
|
|
||||||
In most cases, Angular sets the reference variable's value to the element on which it was declared.
|
In most cases, Angular sets the reference variable's value to the element on which it is declared.
|
||||||
In the previous example, `phone` refers to the _phone number_ `<input>` box.
|
In the previous example, `phone` refers to the phone number `<input>`.
|
||||||
The phone button click handler passes the _input_ value to the component's `callPhone` method.
|
The button's click handler passes the `<input>` value to the component's `callPhone()` method.
|
||||||
But a directive can change that behavior and set the value to something else, such as itself.
|
|
||||||
The `NgForm` directive does that.
|
|
||||||
|
|
||||||
The following is a *simplified* version of the form example in the [Forms](guide/forms) guide.
|
The `NgForm` directive can change that behavior and set the value to something else. In the following example, the template reference variable, `itemForm`, appears three times separated
|
||||||
|
by HTML.
|
||||||
|
|
||||||
<code-example path="template-syntax/src/app/hero-form.component.html" header="src/app/hero-form.component.html" linenums="false">
|
<code-example path="template-reference-variables/src/app/app.component.html" region="ngForm" header="src/app/hero-form.component.html" linenums="false">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
A template reference variable, `heroForm`, appears three times in this example, separated
|
The reference value of itemForm, without the ngForm attribute value, would be
|
||||||
by a large amount of HTML.
|
the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement).
|
||||||
What is the value of `heroForm`?
|
There is, however, a difference between a Component and a Directive in that a `Component
|
||||||
|
`will be referenced without specifying the attribute value, and a `Directive` will not
|
||||||
|
change the implicit reference (that is, the element).
|
||||||
|
|
||||||
If Angular hadn't taken it over when you imported the `FormsModule`,
|
|
||||||
it would be the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement).
|
|
||||||
The `heroForm` is actually a reference to an Angular [NgForm](api/forms/NgForm "API: NgForm")
|
However, with `NgForm`, `itemForm` is a reference to the [NgForm](api/forms/NgForm "API: NgForm")
|
||||||
directive with the ability to track the value and validity of every control in the form.
|
directive with the ability to track the value and validity of every control in the form.
|
||||||
|
|
||||||
The native `<form>` element doesn't have a `form` property.
|
The native `<form>` element doesn't have a `form` property, but the `NgForm` directive does, which allows disabling the submit button
|
||||||
But the `NgForm` directive does, which explains how you can disable the submit button
|
if the `itemForm.form.valid` is invalid and passing the entire form control tree
|
||||||
if the `heroForm.form.valid` is invalid and pass the entire form control tree
|
to the parent component's `onSubmit()` method.
|
||||||
to the parent component's `onSubmit` method.
|
|
||||||
|
|
||||||
<h3 class="no-toc">Template reference variable warning notes</h3>
|
<h3 class="no-toc">Template reference variable considerations</h3>
|
||||||
|
|
||||||
A template _reference_ variable (`#phone`) is _not_ the same as a template _input_ variable (`let phone`)
|
A template _reference_ variable (`#phone`) is not the same as a template _input_ variable (`let phone`) such as in an [`*ngFor`](guide/template-syntax#template-input-variable).
|
||||||
such as you might see in an [`*ngFor`](guide/template-syntax#template-input-variable).
|
See [_Structural Directives_](guide/structural-directives#template-input-variable) for more information.
|
||||||
Learn the difference in the [_Structural Directives_](guide/structural-directives#template-input-variable) guide.
|
|
||||||
|
|
||||||
The scope of a reference variable is the _entire template_.
|
The scope of a reference variable is the entire template. So, don't define the same variable name more than once in the same template as the runtime value will be unpredictable.
|
||||||
Do not define the same variable name more than once in the same template.
|
|
||||||
The runtime value will be unpredictable.
|
#### Alternative syntax
|
||||||
|
|
||||||
You can use the `ref-` prefix alternative to `#`.
|
You can use the `ref-` prefix alternative to `#`.
|
||||||
This example declares the `fax` variable as `ref-fax` instead of `#fax`.
|
This example declares the `fax` variable as `ref-fax` instead of `#fax`.
|
||||||
|
|
||||||
<code-example path="template-syntax/src/app/app.component.html" region="ref-fax" header="src/app/app.component.html" linenums="false">
|
|
||||||
|
<code-example path="template-reference-variables/src/app/app.component.html" region="ref-fax" header="src/app/app.component.html" linenums="false">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user