Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In widget.Form, Validateable items don't show their error text unless they are widget.Entry or have HintText set #5194

Open
2 tasks done
ncw opened this issue Oct 14, 2024 · 0 comments
Labels
unverified A bug that has been reported but not verified

Comments

@ncw
Copy link

ncw commented Oct 14, 2024

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

When creating a widget.Form if the widget satisfies the widget the fyne.Validatable then it should show red error text if the validation fails.

However this only happens for widget.Entry or with form items with HintText set.

How to reproduce

First run the program below. You will see that it creates a form with two validated items. The plain one works fine, but the wrapped one does not - the error text does not appear.

If you then uncomment the line //formItem.HintText = "Hint" // Hint needs to be not "" to make validation appear then the error text will appear.

PS Note you need to type something in the box and delete it to get the error message to appear - not sure if this is working as intended or not!

Screenshots

Form without HintText set - notice the validation line is not appearing for the "with help" widget

image

Now with HintText set

image

And showing the error

image

Example code

package main

import (
	"errors"
	"fmt"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
)

// Wrap any widget with a help button next to it
type WithHelp struct {
	widget.BaseWidget
	originalWidget fyne.CanvasObject
	helpButton     *widget.Button
	content        *fyne.Container
}

// check interfaces
var _ fyne.Validatable = &WithHelp{}

// Create a new widget with a help button next to it
//
// Aims to preserve the Validateable status of the wrapped widget
func NewWithHelp(originalWidget fyne.CanvasObject, helpText string) *WithHelp {
	h := &WithHelp{
		originalWidget: originalWidget,
		helpButton: widget.NewButtonWithIcon("", theme.HelpIcon(), func() {
			fyne.CurrentApp().SendNotification(&fyne.Notification{
				Title:   "Help",
				Content: helpText,
			})
		}),
	}
	h.content = container.NewBorder(nil, nil, nil, h.helpButton, h.originalWidget, h.helpButton)
	h.ExtendBaseWidget(h)
	return h
}

// Render the combined originalWidget and helpButton
func (h *WithHelp) CreateRenderer() fyne.WidgetRenderer {
	return widget.NewSimpleRenderer(h.content)
}

// Forward Validate if possible to originalWidget
func (h *WithHelp) Validate() error {
	if do, ok := h.originalWidget.(fyne.Validatable); ok {
		err := do.Validate()
		h.Refresh() // Update the widget's appearance based on validation state
		return err
	}
	return nil
}

// Forward SetOnValidationChanged if possible to originalWidget
func (h *WithHelp) SetOnValidationChanged(callback func(error)) {
	if do, ok := h.originalWidget.(fyne.Validatable); ok {
		do.SetOnValidationChanged(func(err error) {
			callback(err)
			h.Refresh() // Update the widget's appearance when validation changes
		})
	}
}

func main() {
	myApp := app.New()
	myWindow := myApp.NewWindow("Form test with Validateable widget")

	// Create an entry widget with validation then wrap it in a WithHelp
	entry := widget.NewEntry()
	entry.Validator = func(val string) error {
		if val == "" {
			return errors.New("Can't be empty")
		}
		return nil
	}
	withHelp := NewWithHelp(entry, "This is help text for item1")

	// Create an plain entry widget with validation
	entryPlain := widget.NewEntry()
	entryPlain.Validator = func(val string) error {
		if val == "" {
			return errors.New("Can't be empty")
		}
		return nil
	}

	formItem := widget.NewFormItem("with help", withHelp)
	//formItem.HintText = "Hint" // Hint needs to be not "" to make validation appear

	plainFormItem := widget.NewFormItem("plain", entryPlain)

	form := widget.NewForm(
		formItem,
		plainFormItem,
	)
	form.OnSubmit = func() {
		fmt.Println("Submit")
	}
	form.OnCancel = func() {
		myWindow.Close()
		fmt.Println("Cancel")
	}

	myWindow.SetContent(container.NewVBox(form))
	myWindow.Resize(fyne.NewSize(400, 10))
	myWindow.ShowAndRun()
}

Fyne version

7d81356 (master)

Also replicates on

1325f0d (develop)

Go compiler version

go1.23.2

Operating system and version

Ubuntu 22.04.5 LTS

Additional Information

I looked at trying to fix this. I think this is caused by the specific casts to *Entry here

fyne/widget/form.go

Lines 353 to 356 in 7d81356

showHintIfError := false
if e, ok := item.Widget.(*Entry); ok && (!e.dirty || e.focused) {
showHintIfError = true
}

But I'm not confident enough I understand the problem to fix it, but willing to have a go given a hint!

@ncw ncw added the unverified A bug that has been reported but not verified label Oct 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unverified A bug that has been reported but not verified
Projects
None yet
Development

No branches or pull requests

1 participant