#Signal Form value goes out of sync with its Field Tree

24 messages · Page 1 of 1 (latest)

viscid pine
#

I've been trying out the experimental signal forms for my latest project and have been running into difficulties.

I am making an editable paginated Table controlled by signal forms. The model looks something like

tableModel: {
    pages: Page[]
}

interface Page {
    rows: Row[]
}

interface Row {
   foo: string
   bar: string
   ...
}

The initial model contains a single page[0], but a second page is loaded in the background and set into the model. Calling tableModel().value().pages[1] returns a valid Page object; the tree for the first page tableModel.pages[0] is also fine; but the tree for the second page tableModel.pages[1] is undefined.

I tried recreating just this bug in its own bug project but wasn't successful, so it's somehow tied to my app logic. But regardless, this is a bug in Angular, right? Shouldn't the form's Field Tree always have the same Fields as its Value? 😕

ocean notch
blissful pawn
#

this is a bug in Angular, right?
Probably not. Especially given that you can't reproduce it.
Without a reproduction, we can't say for sure.

viscid pine
#

Is the field tree staying in sync with the value not the specification of how signal forms work?

ocean notch
strong marten
#

Maybe you are mutating an array directly? That is not a good idea when using signals. But that's just guessing

viscid pine
#

I'll work on a reproduction project. @strong marten , what should I be careful of with arrays?

ocean notch
strong marten
#

Don't mutate an array that's inside a signal. As far as the signal world is concerned, the value has not changed, it's still the same array.
So instead of thing().push(...) you do thing.update(v => [...v, newValue])

viscid pine
#

I don't do that, but I did re-use an array reference between two instances of one signal. Changing that seems to have fixed the bug; give me a moment to get the code over

strong marten
#

"two instances of one signal"? What does that mean?

viscid pine
#

Before I had

updatePage(pageNumber: newPage: Page){

this.tableModel( (previous) => {
    previous.pages[pageNumber] = newPage;
    return {
      pages: previous.pages
    }
  }
}

What seems to fix it is

updatePage(pageNumber: newPage: Page){

this.tableModel( (previous) => {
    const updatedPages = [...previous.pages];
    updatedPages[pageNumber] = newPage;
    return {
      pages: updatedPages
    }
  }
}
#

But the broken version still returned a new reference. And I haven't overwritten the equals() of that signal

strong marten
#

Yes, you're mutating the array in the first example. push is just one way you can mutate an array.

viscid pine
#

Aha

#

So the form internally has a value() signal for the page array

#

It doesn't update it because the reference is the same

strong marten
night bone
#

That's acceptable as long as you signal has equals: () => false.

viscid pine
#

It makes sense, thank you!

#

I thought it was sufficient to have the form model not be equal

strong marten
#

Right?

#

And I would still say you really shouldn't do this. Just make your data immutable when using signals.