docs: format example code blocks for consistency and readability and keep only file name in header

This commit is contained in:
Shuaib Hasan Akib 2025-11-21 09:52:34 +06:00 committed by Kirill Cherkashin
parent 34fa11ec9d
commit 9565938534
5 changed files with 79 additions and 80 deletions

View file

@ -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.

View file

@ -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

View file

@ -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>

View file

@ -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>`

View file

@ -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: