forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build: add rules for generating block/element API data (angular#52480)
Adds build rules for "artificially" generating `DocEntry` collections for block and element APIs. The two rules are very similar, but _just_ different enough that it's worth having two separate implementations. PR Close angular#52480
- Loading branch information
Showing
18 changed files
with
613 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
load("//tools:defaults.bzl", "nodejs_binary", "ts_library") | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
ts_library( | ||
name = "generate_element_api_json_lib", | ||
srcs = ["generate_element_api_json.ts"], | ||
deps = [ | ||
"//packages/compiler-cli", | ||
"@npm//@types/node", | ||
], | ||
) | ||
|
||
nodejs_binary( | ||
name = "generate_element_api_json", | ||
data = [ | ||
":generate_element_api_json_lib", | ||
], | ||
entry_point = ":generate_element_api_json.ts", | ||
) | ||
|
||
ts_library( | ||
name = "generate_block_api_json_lib", | ||
srcs = ["generate_block_api_json.ts"], | ||
deps = [ | ||
"//packages/compiler-cli", | ||
"@npm//@types/node", | ||
], | ||
) | ||
|
||
nodejs_binary( | ||
name = "generate_block_api_json", | ||
data = [ | ||
":generate_block_api_json_lib", | ||
], | ||
entry_point = ":generate_block_api_json.ts", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
load("//tools/manual_api_docs:generate_block_api_json.bzl", "generate_block_api_json") | ||
|
||
generate_block_api_json( | ||
name = "blocks", | ||
srcs = glob(["*.md"]), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
A type of [block](api/core/defer) that can be used to defer load the JavaScript for components, | ||
directives and pipes used inside a component template. | ||
|
||
## Syntax | ||
|
||
```html | ||
@defer ( on <trigger>; when <condition>; prefetch on <trigger>; prefetch when <condition> ) { | ||
<!-- deferred template fragment --> | ||
<calendar-cmp /> | ||
} @placeholder ( minimum? <duration> ) { | ||
<!-- placeholder template fragment --> | ||
<p>Placeholder</p> | ||
} @loading ( minimum? <duration>; after? <duration> ) { | ||
<!-- loading template fragment --> | ||
<img alt="loading image" src="loading.gif" /> | ||
} @error { | ||
<!-- error template fragment --> | ||
<p>An loading error occured</p> | ||
} | ||
``` | ||
|
||
## Description | ||
|
||
### Blocks | ||
|
||
Supported sections of a defer block. Note: only the @defer block template fragment is deferred | ||
loaded. The remaining optional blocks are eagerly loaded. | ||
|
||
| block | Description | | ||
|----------------|----------------------------------------------------------| | ||
| `@defer` | The defer loaded block of content | | ||
| `@placeholder` | Content shown prior to defer loading (Optional) | | ||
| `@loading` | Content shown during defer loading (Optional) | | ||
| `@error` | Content shown when defer loading errors occur (Optional) | | ||
|
||
<h3>Triggers</h3> | ||
|
||
Triggers provide conditions for when defer loading occurs. Some allow a template reference variable | ||
as an optional parameter. Separate multiple triggers with a semicolon. | ||
|
||
| trigger | Triggers... | | ||
|---------------------------------|-----------------------------------------------| | ||
| `on idle` | when the browser reports idle state (default) | | ||
| `on viewport(<elementRef>?)` | when the element enters the viewport | | ||
| `on interaction(<elementRef>?)` | when clicked, touched, or focused | | ||
| `on hover(<elementRef>?)` | when element has been hovered | | ||
| `on immediate` | when the page finishes rendering | | ||
| `on timer(<duration>)` | after a specific timeout | | ||
| `when <condition>` | on a custom condition | | ||
|
||
<h2>Prefetch</h2> | ||
|
||
Configures prefetching of the defer block used in the `@defer` parameters, but does not affect | ||
rendering. Rendering is handled by the standard `on` and `when` conditions. Separate multiple | ||
prefetch configurations with a semicolon. | ||
|
||
```html | ||
@defer (prefetch on <trigger>; prefetch when <condition>) { | ||
<!-- deferred template fragment --> | ||
} | ||
``` | ||
|
||
Learn more in the [defer loading guide](guide/defer). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
The `@for` block repeatedly renders content of a block for each item in a collection. | ||
|
||
## Syntax | ||
|
||
```html | ||
@for (item of items; track item.name) { | ||
<li> {{ item.name }} </li> | ||
} @empty { | ||
<li> There are no items. </li> | ||
} | ||
``` | ||
|
||
## Description | ||
|
||
The `@for` block renders its content in response to changes in a collection. Collections can be any | ||
JavaScript [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), | ||
but there are performance advantages of using a regular `Array`. | ||
|
||
You can optionally include an `@empty` section immediately after the `@for` block content. The | ||
content of the `@empty` block displays when there are no items. | ||
|
||
<h3> track and objects identity </h3> | ||
|
||
The value of the `track` expression determines a key used to associate array items with the views in | ||
the DOM. Having clear indication of the item identity allows Angular to execute a minimal set of DOM | ||
operations as items are added, removed or moved in a collection. | ||
|
||
Loops over immutable data without `trackBy` as one of the most common causes for performance issues | ||
across Angular applications. Because of the potential for poor performance, the `track` expression | ||
is required for the `@for` loops. When in doubt, using `track $index` is a good default. | ||
|
||
<h3> `$index` and other contextual variables </h3> | ||
|
||
Inside `@for` contents, several implicit variables are always available: | ||
|
||
| Variable | Meaning | | ||
| -------- | ------- | | ||
| `$count` | Number of items in a collection iterated over | | ||
| `$index` | Index of the current row | | ||
| `$first` | Whether the current row is the first row | | ||
| `$last` | Whether the current row is the last row | | ||
| `$even` | Whether the current row index is even | | ||
| `$odd` | Whether the current row index is odd | | ||
|
||
These variables are always available with these names, but can be aliased via a `let` segment: | ||
|
||
```html | ||
@for (item of items; track item.id; let idx = $index, e = $even) { | ||
Item #{{ idx }}: {{ item.name }} | ||
} | ||
``` | ||
|
||
The aliasing is especially useful in case of using nested `@for` blocks where contextual variable | ||
names could collide. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
The `@if` block conditionally displays its content when its condition expression is truthy. | ||
|
||
## Syntax | ||
|
||
```html | ||
@if (a > b) { | ||
{{a}} is greater than {{b}} | ||
} @else if (b > a) { | ||
{{a}} is less than {{b}} | ||
} @else { | ||
{{a}} is equal to {{b}} | ||
} | ||
``` | ||
|
||
## Description | ||
|
||
Content is added and removed from the DOM based on the evaluation of conditional expressions in | ||
the `@if` and `@else` blocks. | ||
|
||
The built-in `@if` supports referencing of expression results to keep a solution for common coding | ||
patterns: | ||
|
||
```html | ||
@if (users$ | async; as users) { | ||
{{ users.length }} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
The `@switch` block is inspired by the JavaScript `switch` statement: | ||
|
||
## Syntax | ||
|
||
```html | ||
@switch (condition) { | ||
@case (caseA) { | ||
Case A. | ||
} | ||
@case (caseB) { | ||
Case B. | ||
} | ||
@default { | ||
Default case. | ||
} | ||
} | ||
``` | ||
|
||
## Description | ||
|
||
The `@switch` blocks displays content selected by one of the cases matching against the conditional | ||
expression. The value of the conditional expression is compared to the case expression using | ||
the `===` operator. | ||
|
||
The `@default` block is optional and can be omitted. If no `@case` matches the expression and there | ||
is no `@default` block, nothing is shown. | ||
|
||
**`@switch` does not have fallthrough**, so you do not need an equivalent to a `break` or `return` | ||
statement. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
load("//tools/manual_api_docs:generate_element_api_json.bzl", "generate_element_api_json") | ||
|
||
generate_element_api_json( | ||
name = "elements", | ||
srcs = glob(["*.md"]), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
A special element that can hold structural directives without adding new elements to the DOM. | ||
|
||
The `<ng-container>` allows us to use structural directives without any extra element, making sure | ||
that the only DOM changes being applied are those dictated by the directives themselves. | ||
|
||
This not only increases performance \(even so slightly\) since the browser ends up rendering less | ||
elements but can also be a valuable asset in having cleaner DOMs and styles alike. | ||
|
||
It can for example enable us to use structural directives without breaking styling dependent on a | ||
precise DOM structure \(as for example the ones we get when using flex containers, margins, the | ||
child combinator selector, etc.\). | ||
|
||
## Usage notes | ||
|
||
### With `*NgIf`s | ||
|
||
One common use case of `<ng-container>` is alongside the `*ngIf` structural directive. By using the | ||
special element we can produce very clean templates easy to understand and work with. | ||
|
||
For example, we may want to have a number of elements shown conditionally but they do not need to be | ||
all under the same root element. That can be easily done by wrapping them in such a block: | ||
|
||
<code-example format="html" language="html"> | ||
|
||
<ng-container *ngIf="condition"> | ||
… | ||
</ng-container> | ||
|
||
</code-example> | ||
|
||
This can also be augmented with an `else` statement alongside an `<ng-template>` as: | ||
|
||
<code-example format="html" language="html"> | ||
|
||
<ng-container *ngIf="condition; else templateA"> | ||
… | ||
</ng-container> | ||
<ng-template #templateA> | ||
… | ||
</ng-template> | ||
|
||
</code-example> | ||
|
||
### Combination of multiple structural directives | ||
|
||
Multiple structural directives cannot be used on the same element; if you need to take advantage of | ||
more than one structural directive, it is advised to use an `<ng-container>` per structural | ||
directive. | ||
|
||
The most common scenario is with `*ngIf` and `*ngFor`. For example, let's imagine that we have a | ||
list of items but each item needs to be displayed only if a certain condition is true. We could be | ||
tempted to try something like: | ||
|
||
<code-example format="html" language="html"> | ||
|
||
<ul> | ||
<li *ngFor="let item of items" *ngIf="item.isValid"> | ||
{{ item.name }} | ||
</li> | ||
</ul> | ||
|
||
</code-example> | ||
|
||
As we said that would not work, what we can do is to simply move one of the structural directives to | ||
an `<ng-container>` element, which would then wrap the other one, like so: | ||
|
||
<code-example format="html" language="html"> | ||
|
||
<ul> | ||
<ng-container *ngFor="let item of items"> | ||
<li *ngIf="item.isValid"> | ||
{{ item.name }} | ||
</li> | ||
</ng-container> | ||
</ul> | ||
|
||
</code-example> | ||
|
||
This would work as intended without introducing any new unnecessary elements in the DOM. | ||
|
||
For more information see [one structural directive per element](guide/structural-directives#one-per-element). | ||
|
||
### Use alongside ngTemplateOutlet | ||
|
||
The `NgTemplateOutlet` directive can be applied to any element but most of the time it's applied | ||
to `<ng-container>` ones. By combining the two, we get a very clear and easy to follow HTML and DOM | ||
structure in which no extra elements are necessary and template views are instantiated where | ||
requested. | ||
|
||
For example, imagine a situation in which we have a large HTML, in which a small portion needs to be | ||
repeated in different places. A simple solution is to define an `<ng-template>` containing our | ||
repeating HTML and render that where necessary by using `<ng-container>` alongside | ||
an `NgTemplateOutlet`. | ||
|
||
Like so: | ||
|
||
<code-example format="html" language="html"> | ||
|
||
<!-- … --> | ||
|
||
<ng-container *ngTemplateOutlet="tmpl; context: {$implicit: 'Hello'}"> | ||
</ng-container> | ||
|
||
<!-- … --> | ||
|
||
<ng-container *ngTemplateOutlet="tmpl; context: {$implicit: 'World'}"> | ||
</ng-container> | ||
|
||
<!-- … --> | ||
|
||
<ng-template #tmpl let-text> | ||
<h1>{{ text }}</h1> | ||
</ng-template> | ||
|
||
</code-example> | ||
|
||
For more information regarding `NgTemplateOutlet`, see | ||
the [`NgTemplateOutlet`s api documentation page](api/common/NgTemplateOutlet). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
The `<ng-content>` element specifies where to project content inside a component template. | ||
|
||
## Attributes | ||
|
||
| Attribute | Description | | ||
|---------------|-------------------------------------------------------------------------| | ||
| `select` | CSS selector. Matching elements are projected into this `<ng-content>`. | | ||
|
||
Only select elements from the projected content that match the given CSS `selector`. | ||
|
||
Angular supports [selectors](https://developer.mozilla.org/docs/Web/CSS/CSS_Selectors) for any | ||
combination of tag name, attribute, CSS class, and the `:not` pseudo-class. |
Oops, something went wrong.