Nested components #176
-
Hi there, first of all, sorry because I do not know if this is the place where people usually ask for information. I am currently developing a complex cli and I just want to use this framework to build it. My main idea was to nest components inside other complex components as javascript framework does such as vue, react, etc... It is possible to to something like this? TextInput component definition type TextInput struct {
textinput textinput.Model
err error
}
func (model TextInput) Init() tea.Cmd {
return textinput.Blink
}
func (model TextInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyEnter, tea.KeyCtrlC, tea.KeyEsc:
return model, tea.Quit
}
case error:
model.err = msg
return model, nil
}
model.textinput, cmd = model.textinput.Update(msg)
return model, cmd
}
func (model TextInput) View() string {
return fmt.Sprintf(
"?\n\n%s\n\n%s",
model.textinput.View(),
"(esc to quit)",
) + "\n"
}
func NewTextInput(placeholder string) TextInput {
textinput := textinput.NewModel()
textinput.Placeholder = placeholder
textinput.CharLimit = TEXT_INPUT_LIMIT
textinput.Width = TEXT_INPUT_WIDTH
textinput.Focus()
return TextInput{textinput, nil}
} View definition type husky struct {
name TextInput
stun TextInput
peer TextInput
current tea.Model
cursor int
}
func (view husky) Init() tea.Cmd {
return view.current.Init()
}
func (view husky) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if view.name.textinput.Value() == "" {
return view.name.Update(msg)
}
if view.stun.textinput.Value() == "" {
return view.name.Update(msg)
}
if view.peer.textinput.Value() == "" {
return view.name.Update(msg)
}
return nil, nil
}
func (view husky) View() string {
return view.current.View()
}
func Husky() husky {
name := NewTextInput("name")
stun := NewTextInput("stun")
peer := NewTextInput("peer")
return husky{name, stun, peer, name, 0}
} Thanks in advance! 😄 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Hi! Implementing sub-components is super common in Bubble Tea. In fact, all of the packages in Bubbles, the component library, are merely sub-components. Anyway, your code is more or less on the right track, however you're replacing the entire model in update which is totally doable, however you'll probably find nesting components on your model easier to manage. Here's a hypothetical example of what that could look like: type model struct {
// Sub-models
a tea.Model
b tea.Model
}
func (m model) Init() tea.Cmd {
// Initialize sub-models
return tea.Batch(
m.a.Init(),
m.b.Init(),
)
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var (
cmd tea.Cmd
cmds []tea.Cmd
)
// Handle any top-level messages
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c":
// Send the quit command. But also notice that we're not returning
// here because in this example case we also want the sub-models to
// do their updates too.
cmds = append(cmds, tea.Quit)
}
}
// Handle updates for sub-model A
m.a, cmd = m.a.Update(msg)
cmds = append(cmds, cmd)
// Handle updates for sub-model B
m.b, cmd = m.b.Update(msg)
cmds = append(cmds, cmd)
// Return updated model and any new commands
return m, tea.Batch(cmds...)
}
func (m model) View() string {
// Render sub model views
s := m.a.View()
s += m.b.View()
return s
} If course, in a real-world scenario there would be more logic in your |
Beta Was this translation helpful? Give feedback.
Hi! Implementing sub-components is super common in Bubble Tea. In fact, all of the packages in Bubbles, the component library, are merely sub-components.
Anyway, your code is more or less on the right track, however you're replacing the entire model in update which is totally doable, however you'll probably find nesting components on your model easier to manage. Here's a hypothetical example of what that could look like: