Updating state in sub-model within Init not possible? #781
-
I can't seem to get a sub-model to update internal state from within it's own package main
import (
"log"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
type buffer struct {
messages *[]string
}
type subModel struct {
buffer buffer
}
func (m subModel) Init() tea.Cmd {
return func() tea.Msg {
*m.buffer.messages = append(*m.buffer.messages, "A")
return nil
}
}
func (m subModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
}
func (m subModel) View() string {
return strings.Join(*m.buffer.messages, "\n")
}
type mainModel struct {
subModel subModel
}
func (m mainModel) Init() tea.Cmd {
return nil
}
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
}
}
return m, nil
}
func (m mainModel) View() string {
return m.subModel.View()
}
func main() {
p := tea.NewProgram(mainModel{subModel: subModel{buffer: buffer{messages: new([]string)}}})
if err := p.Start(); err != nil {
log.Fatal(err)
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Hi! So there are two things you'll need to change for this to work. Firstly, return the child model's func (m mainModel) Init() tea.Cmd {
return m.subModel.Init()
} Secondly, // The message that contains the content for updating the buffer
type bufferContentMsg string
// Send a message to update the buffer.
func (m subModel) Init() tea.Cmd {
return bufferContentMsg("A")
}
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
// Update the buffer. You could, of course, also call Update on the sub-model
// here and handle the update there as well.
case bufferContentMsg:
*m.subModel.buffer.messages = append(*m.subModel.buffer.messages, "A")
return m, nil
// etc...
} And, of course, the above changes will require you remove the function call on the submodel's func (m mainModel) Init() tea.Cmd {
return m.subModel.Init
} This may seem convoluted at first but it will keep your code very straightforward, readable, and manageable. Some folks may point out that you could also use pointer receivers on the Speaking of manageable, you may find it easier to keep all your your interdependent data and methods on one model. We find generally find nesting models a common source of complexity because you're constantly managing communication between different parts of your application. |
Beta Was this translation helpful? Give feedback.
-
Thanks @meowgorithm! That's great 🎉 |
Beta Was this translation helpful? Give feedback.
Hi! So there are two things you'll need to change for this to work. Firstly, return the child model's
Init
in the parent'sInit
(Bubble Tea is very mechanical that way):Secondly,
Init
needs to send a message toUpdate
to append to the buffer: