Я работаю с сигналами в 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 также должен быть пустым до тех пор, пока пользователь начинает печатать.
@NarenMurali спасибо за вопрос, я добавил больше информации о том, что я пытаюсь сделать
@Daniel Привет, во-первых, НаренМурали совершенно прав; он всегда будет пуст. Кроме того, я даже не знаю, откуда взялась переменная InitialDisplaySource. Во-вторых, Angular ожидает, что вы будете использовать эффекты не так, поэтому выдает ошибку. Это не рекомендуется, но есть способ включить его, используя то, что предлагает сообщение об ошибке: «ИспользуйтеallowSignalWrites в CreateEffectOptions, чтобы включить эти внутренние эффекты».
Хотя это можно сделать с помощью 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
Вау, спасибо! Я не знал об этом. Как вы думаете, что мне следует сделать со своим ответом? Должен ли я удалить его? Я думал, что @Daniel пытается создать свою собственную «signalFactory», чтобы управлять поисковым термином для каждой строки индивидуально. Не стесняйтесь редактировать.
Я думаю, что сейчас все в порядке. Как только PR будет объединен и этот функционал изменится, было бы хорошо отредактировать ответ.
этот код не имеет смысла, потому что, когда вы устанавливаете сигнал как пустой, он снова запускает эффект и снова очищает начальныйDisplaySource.