fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design
https://fyne.io/
Other
25.13k stars 1.4k forks source link

Entry Validation Broken when using Data binding #1890

Closed AlbinoGeek closed 3 years ago

AlbinoGeek commented 3 years ago

Describe the bug:

Adding a Validator to an Entry that does not belong to a form appears to have no effect on the visual validation of said field, so the point where returning an error from the StringValidator results in a checkmark being shown as if the field passed validation.

To Reproduce:

Steps to reproduce the behaviour:

  1. Use the provided example code
  2. Enter any values into the Entry
  3. Bug

Screenshots:

image

Example code:

package main

import (
    "fmt"
    "time"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/data/binding"
    "fyne.io/fyne/v2/dialog"
    "fyne.io/fyne/v2/widget"
)

var ukDateWithDecimals = "02.01.2006"
var errDateFormat = fmt.Errorf("date must match format: %v", ukDateWithDecimals)

func main() {
    a := app.New()
    w := a.NewWindow("Flight Booker")

    d1 := binding.NewString()
    d2 := binding.NewString()

    t1 := widget.NewEntryWithData(d1)
    t2 := widget.NewEntryWithData(d2)

    // setup Validation on the Entry(s)
    dateValidator := func(s string) (err error) {
        if _, err := time.Parse(ukDateWithDecimals, s); err != nil {
            fmt.Println("Validation Error:", errDateFormat)
            return errDateFormat
        }

        return nil
    }

    t1.Validator = dateValidator
    t2.Validator = dateValidator

    options := []string{
        "one-way flight",
        "return flight",
    }
    combo := widget.NewSelect(options, func(s string) {
        if s == options[0] {
            t2.Disable()
        } else {
            t2.Enable()
        }
    })

    bookPressed := func() {
        msg := ""

        if to := t2.Text; to == "" {
            msg = fmt.Sprintf("Flight booked on %s.", t1.Text)
        } else {
            msg = fmt.Sprintf("Flights booked on %s and %s.", t1.Text, to)
        }

        dialog.ShowInformation("Flight Booked", msg, w)
    }

    // Technically, a `widget.Form` should be used to create this interface,
    // however, this would not "be true" to the example shown in 7guis. The
    // code to use a Form is included for completeness however.
    //
    // form := widget.NewForm(
    //  widget.NewFormItem("", combo),
    //  widget.NewFormItem("From", t1),
    //  widget.NewFormItem("To", t2),
    // )
    // form.SubmitText = "Book"
    // form.OnSubmit = bookPressed
    // w.SetContent(form)
    //
    // If using the form, comment out the button and w.SetContent used below:

    button := widget.NewButton("Book", bookPressed)
    w.SetContent(container.NewVBox(combo, t1, t2, button))
    w.Resize(w.Content().MinSize().Add(fyne.NewSize(80, 0)))
    w.ShowAndRun()
}

Device (please complete the following information):

AlbinoGeek commented 3 years ago

Even calling .SetValidationError(err) on the entry did not cause the field to go into the "error" state.

Simplified code that still reproduces this:

package main

import (
    "fmt"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/data/binding"
    "fyne.io/fyne/v2/widget"
)

func main() {
    a := app.New()
    w := a.NewWindow("Entry Error")
    data := binding.NewString()
    entry := widget.NewEntryWithData(data)

    entry.Validator = func(s string) (err error) {
        err = fmt.Errorf("this is an error")
        entry.SetValidationError(err)
        return
    }

    w.SetContent(entry)

    w.Resize(w.Content().MinSize().Add(fyne.NewSize(80, 0)))

    w.ShowAndRun()
}
andydotxyz commented 3 years ago

Ah data binding. I see now. Maybe the data binding error is stomping over the validation that is set?

andydotxyz commented 3 years ago

fixed on develop :)

kvishal7 commented 10 months ago

is this fixed in master ? I still see this issue in 2.4.0

andydotxyz commented 10 months ago

It was fixed back at v2.1.0 - are you certain you are seeing the exact same issue?

kvishal7 commented 10 months ago

@andydotxyz I was seeing the exact same issue. I used a workaround where I extract the data from the entry directly instead of the binding. But now when I revert the code to the one with binding, the vaildation works! maybe there was sth else which broke the validation.