Как установить новое значение для «Сигнала», который вызывается из «Эффекта»?

Я работаю с сигналами в Angular 17 и хочу обновить значение сигнала, но выдает следующую ошибку:

NG0600: Writing to signals is not allowed in a `computed` or an `effect` by default. Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.

Я искал информацию об этом, но не нашел ничего полезного.

По сути, я пытаюсь обновить значение сигнала после условия, все это вызывается из метода Effect:

Компонент:

export class LibGridViewComponent {
    private _libSubjectsGiproService = inject(LibSubjectsGiproService)

    constructor() {
    effect(() => {
      this.getValuesBySearchSignal()
    });
  }
  
  getValuesBySearchSignal(displaySource?: any): any[] {
    let testArr = [
      {
        "name": "B179 HEPATITIS VIRAL AGUDA NO ESPECIFICADA",
        "value": "B179"
      },
      {
        "name": "B980 HELICOBACTER PYLORI [H.PYLORI] COMO LA CAUSA DE ENFERMEDADES CLASIFICADAS EN OTROS CAPITULOS",
        "value": "B980"
      },
      {
        "name": "C799 TUMOR MALIGNO SECUNDARIO - SITIO NO ESPECIFICADO",
        "value": "C799"
      },
    ]

    let searchTerm = this._libSubjectsGiproService.getSearchTerm()
    
    let foundSource:any = []

    if (searchTerm && searchTerm != '') {
      foundSource = testArr.filter(i => i.name.toLowerCase().includes(searchTerm));

        let currentSource = this.initialDisplaySource.value;
        this.initialDisplaySource.next([...currentSource, ...foundSource]);
        this._libSubjectsGiproService.setSearchTerm('')
    } else {
      this.initialDisplaySource.next([])
    }

    return this.initialDisplaySource.value
  }
}

Услуга:

export class LibSubjectsGiproService {
    searchTerm: WritableSignal<any> = signal<any>('');
    
    setSearchTerm(value: any) {
    this.searchTerm.set(value);
  }

  getSearchTerm() {
    return this.searchTerm();
  }
}

ОБНОВЛЯТЬ: Я попытаюсь добавить больше контекста к тому, что я пытаюсь сделать. У меня есть представление в виде сетки, и один из его столбцов — это «Выбрать» с возможностью поиска элемента на основе ввода пользователя. В таблицу можно добавлять больше строк, но запись, по которой осуществляется поиск элементов, остается с ранее введенным значением, идея в том, что каждый раз при добавлении новой строки сигнал пуст, поэтому начальныйDisplaySource также должен быть пустым до тех пор, пока пользователь начинает печатать.

этот код не имеет смысла, потому что, когда вы устанавливаете сигнал как пустой, он снова запускает эффект и снова очищает начальныйDisplaySource.

Naren Murali 20.06.2024 20:38

@NarenMurali спасибо за вопрос, я добавил больше информации о том, что я пытаюсь сделать

Daniel 20.06.2024 21:40

@Daniel Привет, во-первых, НаренМурали совершенно прав; он всегда будет пуст. Кроме того, я даже не знаю, откуда взялась переменная InitialDisplaySource. Во-вторых, Angular ожидает, что вы будете использовать эффекты не так, поэтому выдает ошибку. Это не рекомендуется, но есть способ включить его, используя то, что предлагает сообщение об ошибке: «ИспользуйтеallowSignalWrites в CreateEffectOptions, чтобы включить эти внутренние эффекты».

Joel Garcia Nuño 20.06.2024 22:03
Тестирование функциональных 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
2
3
156
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Хотя это можно сделать с помощью effect, возможно, это не лучшее решение, поскольку обновление сигнала вызовет эффект, и вам придется выполнить дополнительную работу по повторной настройке сигнала, что в документации не одобряется, вместо этого используйте html. события, которые происходят только тогда, когда пользователь меняет ввод.

Если вы уверены, что вам нужен метод эффекта, воспользуйтесь другим предложением в моем ответе.

По сути, мы запускаем функцию getValuesBySearchSignal, когда пользователь вводит элемент выбора, поскольку вы не поделились HTML-кодом, мы можем использовать (ngModelChange), (change), (input), эти события могут активировать функцию, и вы можете сбросить сигнал и сделать что-нибудь еще.

<input [(ngModel)] = "" (ngModelChange) = "getValuesBySearchSignal()"/>

Мы можем просто использовать allowSignalWrites как true в параметрах эффекта.

  constructor() {
    effect(() => {
      this.getValuesBySearchSignal()
    }, {
        allowSignalWrites: true
    });
  }

Просто помните о недостаткахallowSignalWrites, указанных в документации

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

Внимание: эффект в настоящее время находится в предварительной версии для разработчиков.

Пример кода о том, как включить флаг «allowSignalsWrite»:

  constructor() {
    effect(() => {
      this.getValuesBySearchSignal()
    }, { allowSignalWrites: true } );
  }

Это не рекомендуется и не включено по умолчанию, поскольку вызов сигнала может создать цикл, который приведет к зависанию браузера.

Это может привести к серьезной проблеме, которая трудно обнаружить по мере роста приложения.

Стоит отметить, что effect находится в предварительной версии для разработчиков, и существует открытый запрос на удаление опции allowSignalWrites, всегда разрешающей запись сигналов в эффектах. См. github.com/angular/angular/pull/56501

JSON Derulo 20.06.2024 22:20

Вау, спасибо! Я не знал об этом. Как вы думаете, что мне следует сделать со своим ответом? Должен ли я удалить его? Я думал, что @Daniel пытается создать свою собственную «signalFactory», чтобы управлять поисковым термином для каждой строки индивидуально. Не стесняйтесь редактировать.

Joel Garcia Nuño 20.06.2024 22:29

Я думаю, что сейчас все в порядке. Как только PR будет объединен и этот функционал изменится, было бы хорошо отредактировать ответ.

JSON Derulo 21.06.2024 09:18

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

Как я могу вывести типы аргументов нескольких функций в TypeScript
Сопоставьте значения из NgForm с моделью машинописного текста, определенной в Angular
Могу ли я использовать файлы ts точно так же, как я использую файлы js?
Проблема вывода типа с массивом универсальных объектов конфигурации с разными внутренними типами, которые зависят от другого внутреннего свойства
Почему добавление круглых скобок удаляет «только для чтения [x: число]: число;» из этого типа?
Введите 'строка | логическое значение не может быть назначено для ввода «никогда» в машинописном тексте
Как добавить динамические метаданные на страницу [slug] в маршрутизаторе приложений next.js
Программно переключить свойство, нулевое или необязательное, на обязательное в Zod
Кортеж, который принимает только одно вхождение определенного типа
Как указать значение по умолчанию (но не ноль) в числовом типе в форме zod и response-hooks?