Найти в Дзене

Host-директивы в Angular

Начиная с Angular 15 появилась новая возможность: хост-директивы.
Давайте начнем с примера: @Component({
selector: '...',
host: {
...
'[class.my-disabled-class]': 'disabled',
'[attr.disabled]': 'disabled || null',
'[attr.aria-disabled]': 'disabled || null',
...
},
template: `...`
})
class MyComponent {
@Input() public disabled = false;
// many other stuffs
}
Как можно улучшить этот код? Первая мысль - создать директиву. @Directive({
selector: '[myDisabledState]',
standalone: true,
host: {
'[attr.disabled]': 'disabled || null',
'[attr.aria-disabled]': 'disabled || null',
'[class.rc-disabled]': 'disabled',
},
})
export class DisabledStateDirective {
@Input() public disabled = false;
}
И теперь код можно упростить до такого: @Component({
selector: '...',
host: {
...
},
hostDirectives: [{
directive: DisabledStateDirective,
inputs: ['disabled'],
}],
template: `...`
})
class MyComponent {
// many other stuffs
}
В таком случае код читается проще, и соблюдается

Начиная с Angular 15 появилась новая возможность: хост-директивы.
Давайте начнем с примера:

@Component({
selector: '...',
host: {
...
'[class.my-disabled-class]': 'disabled',
'[attr.disabled]': 'disabled || null',
'[attr.aria-disabled]': 'disabled || null',
...
},
template: `...`
})
class MyComponent {
@Input() public disabled = false;
// many other stuffs
}


Как можно улучшить этот код? Первая мысль - создать директиву.

@Directive({
selector: '[myDisabledState]',
standalone: true,
host: {
'[attr.disabled]': 'disabled || null',
'[attr.aria-disabled]': 'disabled || null',
'[class.rc-disabled]': 'disabled',
},
})
export class DisabledStateDirective {
@Input() public disabled = false;
}


И теперь код можно упростить до такого:

@Component({
selector: '...',
host: {
...
},
hostDirectives: [{
directive: DisabledStateDirective,
inputs: ['disabled'],
}],
template: `...`
})
class MyComponent {
// many other stuffs
}


В таком случае код читается проще, и соблюдается принцип разделения ответственности. Но есть сложность, с выносом логики в директиву теряется доступ к свойству disabled. Разработчики Angular предусмотрели подобное поведение:

@Component({
selector: '...',
host: {
...
},
hostDirectives: [{
directive: DisabledStateDirective,
inputs: ['disabled'],
}],
template: `...`
})
class MyComponent {
private readonly _disabledState: DisabledStateDirective = inject(DisabledStateDirective, { self: true });

public myFunction(): void {
if (this.disabledState.disabled) {

}
}
}

Мы просто используем метод inject, чтобы получить DisabledStateDirective.

Больше материалов с хорошей подсветкой синтаксиса в моем блоге на teletype