Update a node in a tree

It may also be worth looking into tree zippers to handle this:

http://package.elm-lang.org/packages/tomjkidd/elm-multiway-tree-zipper/1.10.2/MultiwayTree

In my Msg type I have:

type Msg
    = ...
    | ToggleOpen (Zipper ContentNode)

So as you walk the tree to render the UI, you set up event handlers with the Zipper positioned at the node being rendered. The Zipper itself is then passed with the event, and you use that to update the tree, then pull it inside out by walking back to the root, and you get the complete new updated tree.

There is a potential stale data problem with this approach though - the Zipper captures the current state, and that may become stale if multiple events occur fast enough that the UI is not refreshed with the new state in between. In practice I have never seen that happen but I also did not use this approach in situations where it seemed likely to happen.