-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e86b7eb
commit d69d0f5
Showing
8 changed files
with
659 additions
and
0 deletions.
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
docs/src/content/docs/utilities/Migrations/host-binding-migration.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,95 @@ | ||
--- | ||
title: Host Binding Migration | ||
description: Schematics for migrating from decorator-based Host Bindings to the new host properties in Angular | ||
entryPoint: plugin/src/generators/convert-host-binding | ||
badge: stable | ||
contributors: ['pawel-ostromecki'] | ||
--- | ||
|
||
Recent Angular releases recommend using the `host` property instead of the `@HostBinding` and `@HostListener` decorators, as these decorators are retained primarily for backward compatibility. This schematic will assist you in migrating your code to utilize the new `host` property. | ||
|
||
### How it works? | ||
|
||
The moment you run the schematics, it will look for all the decorators that have binding and replace them with `host` properties. | ||
|
||
- It will keep the same name for the attributes and properties bindings. | ||
- It will update the component's decorators by adding the `host` property if it does not exist or by adding additional properties within it. | ||
- It won't convert properties to signals. | ||
- It will remove the `@HostListener`, `@HostBinding` decorators. | ||
|
||
### Example | ||
|
||
Before running the schematics: | ||
|
||
```typescript | ||
import { Component, HostBinding, HostListener } from '@angular/core'; | ||
|
||
@Component({ | ||
/* ... */ | ||
}) | ||
export class CustomSlider { | ||
@HostBinding('attr.aria-valuenow') | ||
value: number = 0; | ||
|
||
@HostBinding('tabIndex') | ||
getTabIndex() { | ||
return this.disabled ? -1 : 0; | ||
} | ||
|
||
@HostListener('keydown', ['$event']) | ||
updateValue(event: KeyboardEvent) { | ||
/* ... */ | ||
} | ||
} | ||
``` | ||
|
||
After running the schematics: | ||
|
||
```typescript | ||
import { Component } from '@angular/core'; | ||
|
||
@Component({ | ||
host: { | ||
'[attr.aria-valuenow]': 'value', | ||
'[tabIndex]': 'disabled ? -1 : 0', | ||
'(keydown)': 'updateValue($event)', | ||
}, | ||
}) | ||
export class CustomSlider { | ||
value: number = 0; | ||
disabled: boolean = false; | ||
updateValue(event: KeyboardEvent) { | ||
/* ... */ | ||
} | ||
} | ||
``` | ||
|
||
### Usage | ||
|
||
In order to run the schematics for all the project in the app you have to run the following script: | ||
|
||
```bash | ||
ng g ngxtension:convert-host-binding | ||
``` | ||
|
||
If you want to specify the project name you can pass the `--project` param. | ||
|
||
```bash | ||
ng g ngxtension:convert-host-binding --project=<project-name> | ||
``` | ||
|
||
If you want to run the schematic for a specific component or directive you can pass the `--path` param. | ||
|
||
```bash | ||
ng g ngxtension:convert-host-binding --path=<path-to-ts-file> | ||
``` | ||
|
||
### Usage with Nx | ||
|
||
To use the schematics on a Nx monorepo you just swap `ng` with `nx` | ||
|
||
Example: | ||
|
||
```bash | ||
nx g ngxtension:convert-host-binding --project=<project-name> | ||
``` |
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
116 changes: 116 additions & 0 deletions
116
libs/plugin/src/generators/convert-host-binding/__snapshots__/generator.spec.ts.snap
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,116 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`convert-host-binding generator should convert properly for component 1`] = ` | ||
" | ||
import { Component } from '@angular/core'; | ||
@Component({ | ||
selector: 'my-component', | ||
template: 'My component', | ||
host: { '[class.active]': 'isActive', '[attr.aria-disabled]': 'isDisabled', '[tabIndex]': 'getTabIndex()' } | ||
}) | ||
export class MyComponent { | ||
isActive = true; | ||
get isDisabled() { | ||
return true; | ||
} | ||
getTabIndex() { | ||
return this.isDisabled ? -1 : 0; | ||
} | ||
} | ||
" | ||
`; | ||
|
||
exports[`convert-host-binding generator should convert properly for component with complex host listener 1`] = ` | ||
" | ||
import { Component } from '@angular/core'; | ||
@Component({ | ||
selector: 'my-complex-component', | ||
template: 'My complex component', | ||
host: { '(document:keydown.escape)': 'escapeKeydownHandler($event)', '(mousedown)': 'handleMousedown($event.target)', '(click)': 'handleEventNoArgs()' } | ||
}) | ||
export class MyComplexComponent { | ||
escapeKeydownHandler(event: KeyboardEvent): void { | ||
} | ||
handleMousedown(target: any): void { | ||
} | ||
handleEventNoArgs(): void { | ||
} | ||
} | ||
" | ||
`; | ||
|
||
exports[`convert-host-binding generator should convert properly for component with duplicate host binding 1`] = ` | ||
" | ||
import { Component } from '@angular/core'; | ||
@Component({ | ||
selector: 'my-duplicated-component', | ||
template: 'My duplicated component', | ||
host: { '[class.active]': 'isActive2' } | ||
}) | ||
export class MyDuplicatedComponent { | ||
isActive = true; | ||
isActive2 = true; | ||
" | ||
`; | ||
exports[`convert-host-binding generator should convert properly for component with host property 1`] = ` | ||
" | ||
import { Component } from '@angular/core'; | ||
@Component({ | ||
selector: 'my-component', | ||
template: 'My component', | ||
host: { | ||
'[class.active]': 'isActive', | ||
'[attr.aria-disabled]': 'isDisabled' | ||
} | ||
}) | ||
export class MyComponent { | ||
isActive = true; | ||
get isDisabled() { | ||
return true; | ||
} | ||
} | ||
" | ||
`; | ||
exports[`convert-host-binding generator should convert properly for component with no host binding 1`] = ` | ||
" | ||
import { Component } from '@angular/core'; | ||
@Component({ | ||
selector: 'my-empty-component', | ||
template: 'My empty component', | ||
}) | ||
export class MyEmptyComponent { | ||
} | ||
" | ||
`; | ||
exports[`convert-host-binding generator should convert properly for directive 1`] = ` | ||
" | ||
import { Directive } from '@angular/core'; | ||
@Directive({ | ||
selector: '[myDirective]', | ||
host: { '[class.active]': 'isActive', | ||
'(keydown)': 'updateValue($event)' | ||
} | ||
}) | ||
export class MyDirective { | ||
isActive = true; | ||
updateValue(event: KeyboardEvent) { | ||
} | ||
} | ||
" | ||
`; |
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,4 @@ | ||
import { convertNxGenerator } from '@nx/devkit'; | ||
import { convertHostBindingGenerator } from './generator'; | ||
|
||
export default convertNxGenerator(convertHostBindingGenerator); |
Oops, something went wrong.