mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs: format example code blocks for consistency and readability and keep only file name in header
This commit is contained in:
parent
34fa11ec9d
commit
9565938534
5 changed files with 79 additions and 80 deletions
|
|
@ -67,35 +67,35 @@ ng generate service heroes/hero
|
|||
|
||||
This command creates the following default `HeroService`:
|
||||
|
||||
<docs-code header="heroes/hero.service.ts (CLI-generated)" language="typescript">
|
||||
import { Injectable } from '@angular/core';
|
||||
```ts {header: 'heroes/hero.service.ts (CLI-generated)'}
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class HeroService {}
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
The `@Injectable()` decorator specifies that Angular can use this class in the DI system.
|
||||
The metadata, `providedIn: 'root'`, means that the `HeroService` is provided throughout the application.
|
||||
|
||||
Add a `getHeroes()` method that returns the heroes from `mock.heroes.ts` to get the hero mock data:
|
||||
|
||||
<docs-code header="heroes/hero.service.ts" language="typescript">
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HEROES } from './mock-heroes';
|
||||
```ts {header: 'hero.service.ts'}
|
||||
import {Injectable} from '@angular/core';
|
||||
import {HEROES} from './mock-heroes';
|
||||
|
||||
@Injectable({
|
||||
// declares that this service should be created
|
||||
// by the root application injector.
|
||||
providedIn: 'root',
|
||||
// declares that this service should be created
|
||||
// by the root application injector.
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class HeroService {
|
||||
getHeroes() {
|
||||
return HEROES;
|
||||
getHeroes() {
|
||||
return HEROES;
|
||||
}
|
||||
}
|
||||
}
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
For clarity and maintainability, it is recommended that you define components and services in separate files.
|
||||
|
||||
|
|
@ -106,19 +106,19 @@ To inject a service as a dependency into a component, you can declare a class fi
|
|||
The following example specifies the `HeroService` in the `HeroListComponent`.
|
||||
The type of `heroService` is `HeroService`.
|
||||
|
||||
<docs-code header="heroes/hero-list.component.ts" language="typescript">
|
||||
import { inject } from "@angular/core";
|
||||
```ts
|
||||
import {inject} from '@angular/core';
|
||||
|
||||
export class HeroListComponent {
|
||||
private heroService = inject(HeroService);
|
||||
private heroService = inject(HeroService);
|
||||
}
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
It is also possible to inject a service into a component using the component's constructor:
|
||||
|
||||
<docs-code header="heroes/hero-list.component.ts (constructor signature)" language="typescript">
|
||||
```ts {header: 'hero-list.component.ts (constructor signature)'}
|
||||
constructor(private heroService: HeroService)
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
The `inject` method can be used in both classes and functions, while the constructor method can naturally only be used in a class constructor. However, in either case a dependency may only be injected in a valid [injection context](guide/di/dependency-injection-context), usually in the construction or initialization of a component.
|
||||
|
||||
|
|
@ -127,24 +127,23 @@ The `inject` method can be used in both classes and functions, while the constru
|
|||
When a service depends on another service, follow the same pattern as injecting into a component.
|
||||
In the following example, `HeroService` depends on a `Logger` service to report its activities:
|
||||
|
||||
<docs-code header="heroes/hero.service.ts" language="typescript"
|
||||
highlight="[3,9,12]">
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { HEROES } from './mock-heroes';
|
||||
import { Logger } from '../logger.service';
|
||||
```ts {header: 'hero.service.ts, highlight: [[3],[9],[12]]}
|
||||
import {inject, Injectable} from '@angular/core';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {Logger} from '../logger.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class HeroService {
|
||||
private logger = inject(Logger);
|
||||
private logger = inject(Logger);
|
||||
|
||||
getHeroes() {
|
||||
this.logger.log('Getting heroes.');
|
||||
return HEROES;
|
||||
getHeroes() {
|
||||
this.logger.log('Getting heroes.');
|
||||
return HEROES;
|
||||
}
|
||||
}
|
||||
}
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
In this example, the `getHeroes()` method uses the `Logger` service by logging a message when fetching heroes.
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Every time the value of a form control changes, Angular runs validation and gene
|
|||
You can then inspect the control's state by exporting `ngModel` to a local template variable.
|
||||
The following example exports `NgModel` into a variable called `name`:
|
||||
|
||||
<docs-code header="template/actor-form-template.component.html (name)" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="name-with-error-msg"/>
|
||||
<docs-code header="actor-form-template.component.html (name)" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="name-with-error-msg"/>
|
||||
|
||||
Notice the following features illustrated by the example.
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ For a full list of built-in validators, see the [Validators](api/forms/Validator
|
|||
To update the actor form to be a reactive form, use some of the same
|
||||
built-in validators —this time, in function form, as in the following example.
|
||||
|
||||
<docs-code header="reactive/actor-form-reactive.component.ts (validator functions)" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.1.ts" visibleRegion="form-group"/>
|
||||
<docs-code header="actor-form-reactive.component.ts (validator functions)" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.1.ts" visibleRegion="form-group"/>
|
||||
|
||||
In this example, the `name` control sets up two built-in validators —`Validators.required` and `Validators.minLength(4)`— and one custom validator, `forbiddenNameValidator`.
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ In a reactive form, you can always access any form control through the `get` met
|
|||
|
||||
If you look at the template for the `name` input again, it is fairly similar to the template-driven example.
|
||||
|
||||
<docs-code header="reactive/actor-form-reactive.component.html (name with error msg)" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.html" visibleRegion="name-with-error-msg"/>
|
||||
<docs-code header="actor-form-reactive.component.html (name with error msg)" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.html" visibleRegion="name-with-error-msg"/>
|
||||
|
||||
This form differs from the template-driven version in that it no longer exports any directives. Instead, it uses the `name` getter defined in the component class.
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ The built-in validators don't always match the exact use case of your applicatio
|
|||
Consider the `forbiddenNameValidator` function from the previous example.
|
||||
Here's what the definition of that function looks like.
|
||||
|
||||
<docs-code header="shared/forbidden-name.directive.ts (forbiddenNameValidator)" path="adev/src/content/examples/form-validation/src/app/shared/forbidden-name.directive.ts" visibleRegion="custom-validator"/>
|
||||
<docs-code header="forbidden-name.directive.ts (forbiddenNameValidator)" path="adev/src/content/examples/form-validation/src/app/shared/forbidden-name.directive.ts" visibleRegion="custom-validator"/>
|
||||
|
||||
The function is a factory that takes a regular expression to detect a _specific_ forbidden name and returns a validator function.
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ In the case of an observable, the observable must complete, at which point the f
|
|||
|
||||
In reactive forms, add a custom validator by passing the function directly to the `FormControl`.
|
||||
|
||||
<docs-code header="reactive/actor-form-reactive.component.ts (validator functions)" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.1.ts" visibleRegion="custom-validator"/>
|
||||
<docs-code header="actor-form-reactive.component.ts (validator functions)" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.1.ts" visibleRegion="custom-validator"/>
|
||||
|
||||
### Adding custom validators to template-driven forms
|
||||
|
||||
|
|
@ -115,17 +115,17 @@ For example, the corresponding `ForbiddenValidatorDirective` serves as a wrapper
|
|||
Angular recognizes the directive's role in the validation process because the directive registers itself with the `NG_VALIDATORS` provider, as shown in the following example.
|
||||
`NG_VALIDATORS` is a predefined provider with an extensible collection of validators.
|
||||
|
||||
<docs-code header="shared/forbidden-name.directive.ts (providers)" path="adev/src/content/examples/form-validation/src/app/shared/forbidden-name.directive.ts" visibleRegion="directive-providers"/>
|
||||
<docs-code header="forbidden-name.directive.ts (providers)" path="adev/src/content/examples/form-validation/src/app/shared/forbidden-name.directive.ts" visibleRegion="directive-providers"/>
|
||||
|
||||
The directive class then implements the `Validator` interface, so that it can easily integrate with Angular forms.
|
||||
Here is the rest of the directive to help you get an idea of how it all comes together.
|
||||
|
||||
<docs-code header="shared/forbidden-name.directive.ts (directive)" path="adev/src/content/examples/form-validation/src/app/shared/forbidden-name.directive.ts" visibleRegion="directive"/>
|
||||
<docs-code header="forbidden-name.directive.ts (directive)" path="adev/src/content/examples/form-validation/src/app/shared/forbidden-name.directive.ts" visibleRegion="directive"/>
|
||||
|
||||
Once the `ForbiddenValidatorDirective` is ready, you can add its selector, `appForbiddenName`, to any input element to activate it.
|
||||
For example:
|
||||
|
||||
<docs-code header="template/actor-form-template.component.html (forbidden-name-input)" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="name-input"/>
|
||||
<docs-code header="actor-form-template.component.html (forbidden-name-input)" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="name-input"/>
|
||||
|
||||
HELPFUL: Notice that the custom validation directive is instantiated with `useExisting` rather than `useClass`.
|
||||
The registered validator must be _this instance_ of the `ForbiddenValidatorDirective` —the instance in the form with its `forbiddenName` property bound to "bob".
|
||||
|
|
@ -170,15 +170,13 @@ The validators do this by checking that the actor names and roles do not match.
|
|||
|
||||
The form has the following structure:
|
||||
|
||||
<docs-code language="javascript">
|
||||
|
||||
```ts
|
||||
const actorForm = new FormGroup({
|
||||
'name': new FormControl(),
|
||||
'role': new FormControl(),
|
||||
'skill': new FormControl()
|
||||
'name': new FormControl(),
|
||||
'role': new FormControl(),
|
||||
'skill': new FormControl(),
|
||||
});
|
||||
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
Notice that the `name` and `role` are sibling controls.
|
||||
To evaluate both controls in a single custom validator, you must perform the validation in a common ancestor control: the `FormGroup`.
|
||||
|
|
@ -186,19 +184,20 @@ You query the `FormGroup` for its child controls so that you can compare their v
|
|||
|
||||
To add a validator to the `FormGroup`, pass the new validator in as the second argument on creation.
|
||||
|
||||
<docs-code language="javascript">
|
||||
|
||||
const actorForm = new FormGroup({
|
||||
'name': new FormControl(),
|
||||
'role': new FormControl(),
|
||||
'skill': new FormControl()
|
||||
}, { validators: unambiguousRoleValidator });
|
||||
|
||||
</docs-code>
|
||||
```ts
|
||||
const actorForm = new FormGroup(
|
||||
{
|
||||
'name': new FormControl(),
|
||||
'role': new FormControl(),
|
||||
'skill': new FormControl(),
|
||||
},
|
||||
{validators: unambiguousRoleValidator},
|
||||
);
|
||||
```
|
||||
|
||||
The validator code is as follows.
|
||||
|
||||
<docs-code header="shared/unambiguous-role.directive.ts" path="adev/src/content/examples/form-validation/src/app/shared/unambiguous-role.directive.ts" visibleRegion="cross-validation-validator"/>
|
||||
<docs-code header="unambiguous-role.directive.ts" path="adev/src/content/examples/form-validation/src/app/shared/unambiguous-role.directive.ts" visibleRegion="cross-validation-validator"/>
|
||||
|
||||
The `unambiguousRoleValidator` validator implements the `ValidatorFn` interface.
|
||||
It takes an Angular control object as an argument and returns either null if the form is valid, or `ValidationErrors` otherwise.
|
||||
|
|
@ -210,7 +209,7 @@ If they do match, the actor's role is ambiguous and the validator must mark the
|
|||
|
||||
To provide better user experience, the template shows an appropriate error message when the form is invalid.
|
||||
|
||||
<docs-code header="reactive/actor-form-template.component.html" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.html" visibleRegion="cross-validation-error-message"/>
|
||||
<docs-code header="actor-form-template.component.html" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.html" visibleRegion="cross-validation-error-message"/>
|
||||
|
||||
This `@if` displays the error if the `FormGroup` has the cross validation error returned by the `unambiguousRoleValidator` validator, but only if the user finished [interacting with the form](#control-status-css-classes).
|
||||
|
||||
|
|
@ -219,16 +218,16 @@ This `@if` displays the error if the `FormGroup` has the cross validation error
|
|||
For a template-driven form, you must create a directive to wrap the validator function.
|
||||
You provide that directive as the validator using the [`NG_VALIDATORS` token](/api/forms/NG_VALIDATORS), as shown in the following example.
|
||||
|
||||
<docs-code header="shared/unambiguous-role.directive.ts" path="adev/src/content/examples/form-validation/src/app/shared/unambiguous-role.directive.ts" visibleRegion="cross-validation-directive"/>
|
||||
<docs-code header="unambiguous-role.directive.ts" path="adev/src/content/examples/form-validation/src/app/shared/unambiguous-role.directive.ts" visibleRegion="cross-validation-directive"/>
|
||||
|
||||
You must add the new directive to the HTML template.
|
||||
Because the validator must be registered at the highest level in the form, the following template puts the directive on the `form` tag.
|
||||
|
||||
<docs-code header="template/actor-form-template.component.html" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="cross-validation-register-validator"/>
|
||||
<docs-code header="actor-form-template.component.html" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="cross-validation-register-validator"/>
|
||||
|
||||
To provide better user experience, an appropriate error message appears when the form is invalid.
|
||||
|
||||
<docs-code header="template/actor-form-template.component.html" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="cross-validation-error-message"/>
|
||||
<docs-code header="actor-form-template.component.html" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="cross-validation-error-message"/>
|
||||
|
||||
This is the same in both template-driven and reactive forms.
|
||||
|
||||
|
|
@ -250,13 +249,13 @@ Inspect the control's `pending` property and use it to give visual feedback abou
|
|||
A common UI pattern is to show a spinner while the async validation is being performed.
|
||||
The following example shows how to achieve this in a template-driven form.
|
||||
|
||||
<docs-code language="html">
|
||||
|
||||
```angular-html
|
||||
<input [(ngModel)]="name" #model="ngModel" appSomeAsyncValidator>
|
||||
|
||||
@if(model.pending) {
|
||||
<app-spinner />
|
||||
<app-spinner />
|
||||
}
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
### Implementing a custom async validator
|
||||
|
||||
|
|
@ -266,15 +265,15 @@ To validate the potential role entry, the validator must initiate an asynchronou
|
|||
|
||||
The following code creates the validator class, `UniqueRoleValidator`, which implements the `AsyncValidator` interface.
|
||||
|
||||
<docs-code path="adev/src/content/examples/form-validation/src/app/shared/role.directive.ts" visibleRegion="async-validator"/>
|
||||
<docs-code header="role.directive.ts" path="adev/src/content/examples/form-validation/src/app/shared/role.directive.ts" visibleRegion="async-validator"/>
|
||||
|
||||
The `actorsService` property is initialized with an instance of the `ActorsService` token, which defines the following interface.
|
||||
|
||||
<docs-code language="typescript">
|
||||
```ts
|
||||
interface ActorsService {
|
||||
isRoleTaken: (role: string) => Observable<boolean>;
|
||||
}
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
In a real world application, the `ActorsService` would be responsible for making an HTTP request to the actor database to check if the role is available.
|
||||
From the validator's point of view, the actual implementation of the service is not important, so the example can just code against the `ActorsService` interface.
|
||||
|
|
@ -297,7 +296,7 @@ The `pending` flag is set to `false`, and the form validity is updated.
|
|||
|
||||
To use an async validator in reactive forms, begin by injecting the validator into a property of the component class.
|
||||
|
||||
<docs-code path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.2.ts" visibleRegion="async-validator-inject"/>
|
||||
<docs-code header="actor-form-reactive.component.2.ts" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.2.ts" visibleRegion="async-validator-inject"/>
|
||||
|
||||
Then, pass the validator function directly to the `FormControl` to apply it.
|
||||
|
||||
|
|
@ -305,7 +304,7 @@ In the following example, the `validate` function of `UnambiguousRoleValidator`
|
|||
The value of `asyncValidators` can be either a single async validator function, or an array of functions.
|
||||
To learn more about `FormControl` options, see the [AbstractControlOptions](api/forms/AbstractControlOptions) API reference.
|
||||
|
||||
<docs-code path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.2.ts" visibleRegion="async-validator-usage"/>
|
||||
<docs-code header="actor-form-reactive.component.2.ts" path="adev/src/content/examples/form-validation/src/app/reactive/actor-form-reactive.component.2.ts" visibleRegion="async-validator-usage"/>
|
||||
|
||||
### Adding async validators to template-driven forms
|
||||
|
||||
|
|
@ -313,11 +312,11 @@ To use an async validator in template-driven forms, create a new directive and r
|
|||
|
||||
In the example below, the directive injects the `UniqueRoleValidator` class that contains the actual validation logic and invokes it in the `validate` function, triggered by Angular when validation should happen.
|
||||
|
||||
<docs-code path="adev/src/content/examples/form-validation/src/app/shared/role.directive.ts" visibleRegion="async-validator-directive"/>
|
||||
<docs-code header="role.directive.ts" path="adev/src/content/examples/form-validation/src/app/shared/role.directive.ts" visibleRegion="async-validator-directive"/>
|
||||
|
||||
Then, as with synchronous validators, add the directive's selector to an input to activate it.
|
||||
|
||||
<docs-code header="template/actor-form-template.component.html (unique-unambiguous-role-input)" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="role-input"/>
|
||||
<docs-code header="actor-form-template.component.html (unique-unambiguous-role-input)" path="adev/src/content/examples/form-validation/src/app/template/actor-form-template.component.html" visibleRegion="role-input"/>
|
||||
|
||||
### Optimizing performance of async validators
|
||||
|
||||
|
|
@ -330,15 +329,15 @@ You can delay updating the form validity by changing the `updateOn` property fro
|
|||
|
||||
With template-driven forms, set the property in the template.
|
||||
|
||||
<docs-code language="html">
|
||||
```angular-html
|
||||
<input [(ngModel)]="name" [ngModelOptions]="{updateOn: 'blur'}">
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
With reactive forms, set the property in the `FormControl` instance.
|
||||
|
||||
<docs-code language="typescript">
|
||||
```ts
|
||||
new FormControl('', {updateOn: 'blur'});
|
||||
</docs-code>
|
||||
```
|
||||
|
||||
## Interaction with native HTML form validation
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Instead of using regular anchor elements `<a>` with an `href` attribute, you add
|
|||
|
||||
```angular-ts
|
||||
import {RouterLink} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<nav>
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ The browser uses the `<base href>` value to prefix relative URLs when referencin
|
|||
Add the `<base>` element just after the `<head>` tag.
|
||||
If the `app` folder is the application root, as it is for this application, set the `href` value in `index.html` as shown here.
|
||||
|
||||
<docs-code header="src/index.html (base-href)" path="adev/src/content/examples/router/src/index.html" visibleRegion="base-href"/>
|
||||
<docs-code header="index.html (base-href)" path="adev/src/content/examples/router/src/index.html" visibleRegion="base-href"/>
|
||||
|
||||
### HTML5 URLs and the `<base href>`
|
||||
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ In addition to the default Angular application framework, you will also create a
|
|||
|
||||
1. In your code editor, locate the file, `profile.component.html` and replace the placeholder content with the following HTML.
|
||||
|
||||
<docs-code header="profile/profile.component.html" path="adev/src/content/examples/routing-with-urlmatcher/src/app/profile/profile.component.html"/>
|
||||
<docs-code header="profile/profile.component.html" path="adev/src/content/examples/routing-with-urlmatcher/src/app/profile/profile.component.html"/>
|
||||
|
||||
1. In your code editor, locate the file, `app.component.html` and replace the placeholder content with the following HTML.
|
||||
|
||||
<docs-code header="app.component.html" path="adev/src/content/examples/routing-with-urlmatcher/src/app/app.component.html"/>
|
||||
<docs-code header="app.component.html" path="adev/src/content/examples/routing-with-urlmatcher/src/app/app.component.html"/>
|
||||
|
||||
## Configure your routes for your application
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ This handle is identified by a preceding `@` symbol.
|
|||
|
||||
1. Define the custom route matcher by adding the following code to the application routes.
|
||||
|
||||
<docs-code header="app.routes.ts" path="adev/src/content/examples/routing-with-urlmatcher/src/app/app.routes.ts" visibleRegion="matcher"/>
|
||||
<docs-code header="app.routes.ts" path="adev/src/content/examples/routing-with-urlmatcher/src/app/app.routes.ts" visibleRegion="matcher"/>
|
||||
|
||||
This custom matcher is a function that performs the following tasks:
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue