Skip to content

Commit

Permalink
docs(docs-infra): Adding required and Transform Args into the usage a…
Browse files Browse the repository at this point in the history
…nd documentation of input

I# No commands remaining.
  • Loading branch information
sunilbaba committed Jul 26, 2023
1 parent d6efd71 commit 4d33ce4
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ <h1>Inputs and Outputs</h1>
<!-- #docregion input-parent -->
<app-item-detail [item]="currentItem"></app-item-detail>
<!-- #enddocregion input-parent -->

<!-- #docregion input-parent-metadata -->
<app-item-detail-metadata [item]="currentItem" [itemAvailability]="true"></app-item-detail-metadata>
<!-- #enddocregion input-parent-metadata -->

<hr>

<!-- #docregion output-parent -->
Expand Down
4 changes: 3 additions & 1 deletion aio/content/examples/inputs-outputs/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ItemOutputComponent } from './item-output/item-output.component';
import { InputOutputComponent } from './input-output/input-output.component';
import { InTheMetadataComponent } from './in-the-metadata/in-the-metadata.component';
import { AliasingComponent } from './aliasing/aliasing.component';
import { ItemDetailMetadataComponent } from './item-details-metadata/item-details-metadata.component';


@NgModule({
Expand All @@ -17,7 +18,8 @@ import { AliasingComponent } from './aliasing/aliasing.component';
ItemOutputComponent,
InputOutputComponent,
InTheMetadataComponent,
AliasingComponent
AliasingComponent,
ItemDetailMetadataComponent
],
imports: [
BrowserModule
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<h2>Child component with @Input() metadata configurations</h2>

<p>
Today's item: {{item}}
Item's Availability: {{itemAvailability}}
</p>

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// #docplaster
// #docregion use-input-metadata-required
import { Component, Input } from '@angular/core'; // First, import Input
// #enddocregion use-input-metadata-required
// #docregion use-input-metadata-boolean-transform
import { booleanAttribute } from '@angular/core'; // First, import booleanAttribute
// #enddocregion use-input-metadata-boolean-transform
@Component({
selector: 'app-item-detail-metadata',
templateUrl: './item-details-metadata.component.html'
})


export class ItemDetailMetadataComponent {
// #docregion use-input-metadata-required
@Input({required: true}) item!: string; // Second, decorate the property with required metadata
// #enddocregion use-input-metadata-required

// #docregion use-input-metadata-boolean-transform
@Input({transform: booleanAttribute}) itemAvailability!: boolean; // Second, decorate the property with transform
// #enddocregion use-input-metadata-boolean-transform
}

27 changes: 27 additions & 0 deletions aio/content/guide/inputs-outputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,33 @@ The property `currentItem` and the method `crossOffItem()` are both in the paren

To combine property and event bindings using the banana-in-a-box syntax, `[()]`, see [Two-way Binding](guide/two-way-binding).

## Additional Configurations
### Configuring the child component input as required field

To make `Input` property as required for a child component while passing values from parent component. first import `Input` and then decorate the property with `@Input({ required: true })`, as in the following example.

<code-example header="src/app/item-details-metadata/item-details-metadata.component.ts" path="inputs-outputs/src/app/item-details-metadata/item-details-metadata.component.ts" region="use-input-metadata-required"></code-example>

Next, in the parent template add the following:

<code-example header="src/app/app.component.html" path="inputs-outputs/src/app/app.component.html" region="input-parent-metadata"></code-example>

If required inputs `property binding` in a child component are not specified in the parent component template will result a compile time error :

<div class="alert is-helpful">
NG8008: Required input item from component ItemDetailMetadataComponent must be specified.
</div>

### Configuring the child component input with transform functions

To transform an `Input` property from string to boolean to a child component while passing values from parent component. first import `booleanAttribute` and then decorate the property with `@Input({ transform: booleanAttribute })`, as in the following example.

<code-example header="src/app/item-details-metadata/item-details-metadata.component.ts" path="inputs-outputs/src/app/item-details-metadata/item-details-metadata.component.ts" region="use-input-metadata-boolean-transform"></code-example>

<code-example header="src/app/app.component.html" path="inputs-outputs/src/app/app.component.html" region="input-parent-metadata"></code-example>

Similarly, you can use predefined functions from angular/core library to convert string to number as well, see `numberAttribute`.

<!-- links -->

<!-- external links -->
Expand Down
16 changes: 11 additions & 5 deletions packages/core/src/metadata/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,28 +774,34 @@ export interface InputDecorator {
* one of which is given a special binding name.
*
* ```typescript
* import { Component, Input, numberAttribute, booleanAttribute } from '@angular/core';
* @Component({
* selector: 'bank-account',
* template: `
* Bank Name: {{bankName}}
* Account Id: {{id}}
* Account Status: {{status ? 'Active' : 'InActive'}}
* `
* })
* class BankAccount {
* // This property is bound using its original name.
* @Input() bankName: string;
* // this property value is bound to a different property name
* // Defining argument required as true inside the Input Decorator
* // makes this property deceleration as mandatory
* @Input({ required: true }) bankName!: string;
* // Argument alias makes this property value is bound to a different property name
* // when this component is instantiated in a template.
* @Input('account-id') id: string;
*
* // Argument transform convert the input value from string to number
* @Input({ alias:'account-id', transform: numberAttribute }) id: number;
* // Argument transform the input value from string to boolean
* @Input({ transform: booleanAttribute }) status: boolean;
* // this property is not bound, and is not automatically updated by Angular
* normalizedBankName: string;
* }
*
* @Component({
* selector: 'app',
* template: `
* <bank-account bankName="RBC" account-id="4747"></bank-account>
* <bank-account bankName="RBC" account-id="4747" status="true"></bank-account>
* `
* })
* class App {}
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/util/coercion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
/**
* Transforms a value (typically a string) to a boolean.
* Intended to be used as a transform function of an input.
*
* @usageNotes
* @Input({ transform: booleanAttribute }) status!: boolean;
*
* @param value Value to be transformed.
*
* @publicApi
Expand All @@ -23,6 +27,9 @@ export function booleanAttribute(value: unknown): boolean {
* @param value Value to be transformed.
* @param fallbackValue Value to use if the provided value can't be parsed as a number.
*
* @usageNotes
* @Input({ transform: numberAttribute }) id!: number;
*
* @publicApi
*/
export function numberAttribute(value: unknown, fallbackValue = NaN): number {
Expand Down

0 comments on commit 4d33ce4

Please sign in to comment.