Напечатайте охранников, использующих компьютерный сигнал?

Можно ли использовать сигнал computed для ввода Guard в шаблоне? Я использую Angular 17.0.0 (17.1.0 требуется для сигналов input, которые мы не можем изменить для этой версии библиотеки).

У меня есть два теста внутри этого компонента: один с использованием сигнала isItem и один с использованием функции isItemFn.

  • isItem кажется, не позволяет мне печатать this.item.
  • isItemFn позволяет мне печатать this.item.

Поскольку значение item может быть одним из трех (подробнее об этом позже), мне нужен способ применить защиту типа в шаблоне, и я надеялся, что сигналы помогут, но пока этого не произошло. Есть ли способ сделать это без использования функции или канала?

@Component({})
export class CompositeChipsDisplayComponent<T> {
  @Input() item!: T;

  // Doesn't allow for type guards in the template
  isItem = computed(() => this.item instanceof CompositeChipsItemDirective);

  // Does allow for type guards in the template (but runs too often)
  isItemFn(item: unknown): item is CompositeChipsItemDirective {
    return item instanceof CompositeChipsItemDirective;
  }
}
<!-- Types work within the `if` statement when using a function -->
@if (isItemFn(item)) {
  <button class = "item">
    {{ item.label }}
  </button>
}

<!-- Types do not work within the `if` statement when using a signal -->
@if (isItem()) {
  <button class = "item">
    {{ item.label }}
  </button>
}

Вот как выглядит результат в моем редакторе:

this.item не является сигналом. Почему вы вообще используете компьютерный сигнал? Он никогда не будет обновляться после инициализации. Если бы это был входной сигнал , это имело бы больше смысла.
JSON Derulo 31.07.2024 16:40

Наверное, я никогда об этом не думал, есть идеи получше? У меня нет доступа к 17.1.x для сигналов input. Трубы — мой единственный вариант здесь?

Get Off My Lawn 31.07.2024 16:42
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблемы с вашим кодом следующие.

  1. Вы используете instanceof CompositeChipsItemDirective, который преобразует вычисленное значение в сигнал boolean, вместо этого вам следует просто вернуть сигнал после приведения его к типу директивы.

  2. Вы используете вычисление в HTML, но снова используете исходный ввод внутри шаблона, обращаясь к метке. Вместо этого используйте синтаксис @if as и тип, полученный из вычисленного сигнала, и все должно работать нормально.


import { Component, computed, Directive, Input, Signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

@Directive({
  selector: '[someDirective]',
  standalone: true,
  exportAs: 'someDirective',
})
export class CompositeChipsItemDirective {
  label = 'test';
}

@Component({
  selector: 'app-child',
  standalone: true,
  template: `
    @if (isItemFn(item)) {
      <button class = "item">
        {{ item.label }}
      </button>
    }

    @if (isItem(); as itemCasted) {
      <button class = "item">
        {{ itemCasted.label }}
      </button>
    }
  `,
})
export class CompositeChipsDisplayComponent<T> {
  @Input() item!: T;

  // Doesn't allow for type guards in the template
  isItem: Signal<CompositeChipsItemDirective> = computed(
    () => return this.item instanceof CompositeChipsItemDirective ? this.item as CompositeChipsItemDirective : null;
  );

  // Does allow for type guards in the template (but runs too often)
  isItemFn(item: unknown): item is CompositeChipsItemDirective {
    return item instanceof CompositeChipsItemDirective;
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CompositeChipsDisplayComponent, CompositeChipsItemDirective],
  template: `
    <app-child [item] = "test"/>
    <div #test = "someDirective" someDirective></div>
  `,
})
export class App {
  name = 'Angular';
}

bootstrapApplication(App);

Демо-версия Stackblitz

@if всегда будет возвращать истину, и поскольку у меня есть три разных элемента, он потерпит неудачу, если тип не относится к этому типу. (CompositeChipsItemDirective, CompositeChipsDateDirective, CompositeChipsRangeDirective)

Get Off My Lawn 01.08.2024 18:14

хотя возврат return this.item instanceof CompositeChipsItemDirective ? this.item : null; работает

Get Off My Lawn 01.08.2024 18:20

@GetOffMyLawn извините, не понял эту часть требования, обновил свой ответ, добавив тот же приятный улов!

Naren Murali 01.08.2024 18:45

Другие вопросы по теме