No filho, tenho um campo data
e, com um clique, altero o conteúdo dele. Então, quero que um efeito no pai dispare detectando a referida alteração. Por algum motivo, o efeito não dispara quando altero a entrada do modelo no filho (no entanto, o efeito dispara ao definir o sinal no pai.
A criança tem isso.
export class ChildComponent {
data = model({} as Vm);
onClick() {
console.log("Click alters the data.");
// this.data.set(this.data());
this.data.update(a => a);
}
}
O pai tem isso.
export class ParentComponent {
constructor() {
interval(1000).subscribe(a => console.log("poll: ", this.data()));
effect(() => { console.log("effect: ", this.data()) });
}
data = signal({} as Vm);
ngOnInit() { this.data.set(this.getData()); }
}
Vejo o efeito inicial exibindo um objeto vazio. Então, vejo a atualização do método init do pai. Também vejo a verificação secundária exibindo o valor alterado no filho. No entanto, o efeito não dispara novamente, apenas as duas vezes mencionadas anteriormente.
Estou sem ideias sobre como solucionar o problema mais adiante. Verificando os documentos oficiais, vejo que deveria funcionar (o que, de certa forma, funciona!), mas tenho certeza absoluta se eu executar a alteração no componente filho de forma totalmente correta.
(No cenário real, alterarei apenas um campo em um objeto em uma matriz que faz parte da data
entrada do modelo, mas esse é o próximo passo. Primeiro, quero entender por que fazer set(...)
nor update(...)
aciona o efeito na partent.
O sinal dispara somente quando o valor real muda, já que arrays e objetos são armazenados como referências na memória, se você mudar as propriedades internas a referência de memória não muda, portanto não será detectada como uma mudança. Ela também não muda quando você apenas retorna o objeto como está.
Sinais e Mutabilidade de Array em Angular 18 - Ben Nadel
Problema no Github - Angular 17 - Sinais mutáveis não são suportados
Você pode usar
object destructuring
(para objetos) ou.slice()
o método array (somente arrays) para criar uma nova referência de memória e isso será propagado para o pai. Como a referência de memória é alterada, ela será captada pelo sinal como uma nova alteração.Essa explicação se aplica somente a eles
effect
ecomputed
uma vez que eles reagem somente a mudanças de sinal.Às vezes, você pode notar a atualização fina do HTML para propriedades internas de um sinal contendo um objeto (por exemplo
{{ data()?.qwerty?.test }}
:). Isso não é devido a sinais, mas devido à detecção de alterações em execução (evento Click, executando cdr.detectChanges()), o Angular disparará um ciclo de detecção de alterações e os valores mais recentes serão atualizados para as propriedades aninhadas dentro do sinal. Isso não significa que os sinais suportam objetos mutáveis. É simplesmente um efeito colateral da detecção de alterações em execução.Código completo:
Demonstração do Stackblitz