[PR #300] Added collection of FormItemArgs for each of the form FormItem types #904

Open
opened 2026-03-04 01:08:30 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/rivo/tview/pull/300
Author: @mikeschinkel
Created: 6/10/2019
Status: 🔄 Open

Base: masterHead: formitemargs


📝 Commits (1)

  • 06a95af Add feature-complete FormItemArgs for testing

📊 Changes

6 files changed (+545 additions, -5 deletions)

View changed files

📝 checkbox.go (+93 -0)
📝 dropdown.go (+103 -0)
📝 form.go (+69 -5)
formitemargs.go (+48 -0)
📝 inputfield.go (+125 -0)
passwordfield.go (+107 -0)

📄 Description

After working with Forms for a while and requesting several PRs to make working with them easier I finally had enough with the complexity and decided to implement an alternate method to add form fields than <form>.AddInputField(), <form>.AddPasswordField(), <form>.AddDropdown(), and <form>.AddCheckbox().

The *biggest problem I was trying to fix were that once a field was added it was tedious to then access the form to set other properties not allow to be set in the FormItems New...() method. So I tried numerous iterations with the absolute requirement of backward compatibility and came up with the following, by example:

type Object struct {
    Name     string
    Birthday string
    Password string
    Confirm  string
    FavColor string
    Website  string
    Customer bool
}
type Strings [] string

func (ss Strings) Index(str string) int {
    pos := -1
    for i, v := range ss {
        if v != str {
            continue
        }
        pos = i
        break
    }
    return pos
}

var colors = Strings{"Red", "Green", "Blue"}

func AddFields(form *tview.Form, obj Object) *tview.Form {
    return form.Clear(true).
        AddFormItem(NewInputField(), &InputFieldArgs{
            Label:       "Name:",
            Text:        obj.Name,
            FieldWidth:  40,
            Placeholder: "Enter your full name",
        }).
        AddFormItem(NewInputField(), &InputFieldArgs{
            Label:      "Birthday:",
            Text:       obj.Birthday,
            FieldWidth: 12,
            DoneFunc: func(key tcell.Key) {
                // do something with birthday
            },
        }).
        AddFormItem(NewDropDown(), &DropDownArgs{
            Label:         "Favorite Color?",
            Options:       colors,
            InitialOption: colors.Index(obj.FavColor),
            SelectedFunc: func(option string, optionIndex int) {
                // do something with selected option
            },
        }).
        AddFormItem(NewInputField(), &InputFieldArgs{
            Label:                "Website:",
            Text:                 obj.Website,
            FieldWidth:           60,
            FieldBackgroundColor: tcell.ColorAliceBlue,
            FieldTextColor:       tcell.ColorGreen,
        }).
        AddFormItem(NewCheckbox(), &CheckboxArgs{
            Label:   "Customer?",
            Checked: obj.Customer,

        }).
        AddFormItem(NewPasswordField(), &PasswordFieldArgs{
            Label:      "Password:",
            Text:       obj.Password,
            FieldWidth: 30,
        }).
        AddFormItem(NewPasswordField(), &PasswordFieldArgs{
            Label:      "Confirm:",
            Text:       obj.Confirm,
            FieldWidth: 30,
        })
}

I would have preferred to use the names AddInputField() etc. but could not do so w/o breaking old code so I extended AddFormItem() instead.

There is also a ton of effectively duplicated code, but given the structure of the existing code I could not find a way to consolidate code without breaking backward compatibility. If breaking backward compatibility is an option, I could change the code to be more maintainable, but I needed the functionality and I assumed you would be much less likely to access broken backward compatibility so I went ahead and implemented as is.

Hopefully you will concur this is a good addition to tview and accept this PR? Thanks in advance for considering.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/rivo/tview/pull/300 **Author:** [@mikeschinkel](https://github.com/mikeschinkel) **Created:** 6/10/2019 **Status:** 🔄 Open **Base:** `master` ← **Head:** `formitemargs` --- ### 📝 Commits (1) - [`06a95af`](https://github.com/rivo/tview/commit/06a95af2a234918edf0b7507018fbe534391968b) Add feature-complete FormItemArgs for testing ### 📊 Changes **6 files changed** (+545 additions, -5 deletions) <details> <summary>View changed files</summary> 📝 `checkbox.go` (+93 -0) 📝 `dropdown.go` (+103 -0) 📝 `form.go` (+69 -5) ➕ `formitemargs.go` (+48 -0) 📝 `inputfield.go` (+125 -0) ➕ `passwordfield.go` (+107 -0) </details> ### 📄 Description After working with Forms for a while and requesting several PRs to make working with them easier I finally had enough with the complexity and decided to implement an alternate method to add form fields than `<form>.AddInputField()`, `<form>.AddPasswordField()`, `<form>.AddDropdown()`, and `<form>.AddCheckbox()`. The *biggest problem I was trying to fix were that once a field was added it was tedious to then access the form to set other properties not allow to be set in the `FormItem`s `New...()` method. So I tried numerous iterations with the **absolute requirement of backward compatibility** and came up with the following, by example: ``` type Object struct { Name string Birthday string Password string Confirm string FavColor string Website string Customer bool } type Strings [] string func (ss Strings) Index(str string) int { pos := -1 for i, v := range ss { if v != str { continue } pos = i break } return pos } var colors = Strings{"Red", "Green", "Blue"} func AddFields(form *tview.Form, obj Object) *tview.Form { return form.Clear(true). AddFormItem(NewInputField(), &InputFieldArgs{ Label: "Name:", Text: obj.Name, FieldWidth: 40, Placeholder: "Enter your full name", }). AddFormItem(NewInputField(), &InputFieldArgs{ Label: "Birthday:", Text: obj.Birthday, FieldWidth: 12, DoneFunc: func(key tcell.Key) { // do something with birthday }, }). AddFormItem(NewDropDown(), &DropDownArgs{ Label: "Favorite Color?", Options: colors, InitialOption: colors.Index(obj.FavColor), SelectedFunc: func(option string, optionIndex int) { // do something with selected option }, }). AddFormItem(NewInputField(), &InputFieldArgs{ Label: "Website:", Text: obj.Website, FieldWidth: 60, FieldBackgroundColor: tcell.ColorAliceBlue, FieldTextColor: tcell.ColorGreen, }). AddFormItem(NewCheckbox(), &CheckboxArgs{ Label: "Customer?", Checked: obj.Customer, }). AddFormItem(NewPasswordField(), &PasswordFieldArgs{ Label: "Password:", Text: obj.Password, FieldWidth: 30, }). AddFormItem(NewPasswordField(), &PasswordFieldArgs{ Label: "Confirm:", Text: obj.Confirm, FieldWidth: 30, }) } ``` I would have preferred to use the names `AddInputField()` etc. but could not do so w/o breaking old code so I extended `AddFormItem()` instead. There is also a ton of effectively duplicated code, but given the structure of the existing code I could not find a way to consolidate code without breaking backward compatibility. If breaking backward compatibility is an option, I could change the code to be more maintainable, but I needed the functionality and I assumed you would be much less likely to access broken backward compatibility so I went ahead and implemented as is. Hopefully you will concur this is a good addition to tview and accept this PR? Thanks in advance for considering. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#904
No description provided.