fyne-io/fyne

Data Binding Validation

Open

#1,704 opened on Dec 31, 2020

View on GitHub
 (11 comments) (0 reactions) (0 assignees)Go (1,526 forks)batch import
Hacktoberfestdata binding

Repository metrics

Stars
 (28,262 stars)
PR merge metrics
 (Avg merge 26d 11h) (38 merged PRs in 30d)

Description

Summary

If data binding is meant to be the single source of truth, I would say it needs inline validation.

The Get and Set operating on error makes me feel this could happen within the current API.

Problem

Currently, as the intention is that you load data binding values from preferences (?) -- the only safety that binding grants you is type-conformity. (A binding.String will always return a string.)

However, there is no requirement to match a given format, length, etc (as a developer/program may have.)

This leads to a situation where corrupt preferences can load into and cause a program to crash in an unrecoverable fashion.

Again, under the assumption that the bound variables were the single source of truth.

Possible Solutions

What if bindings had validators? It would only take adding one function and one line of code per binding.

str := binding.NewString()
str.SetValidator(func(s string) error {
  if len(s) < 4 {
    return errors.New("value too short")
  }
})
if err := str.Set("foo"); err != nil {
  panic(err) // value too short
}

positive := binding.NewInt()
positive.SetValidator(func(i int) error {
  if i < 0 {
    return errors.New("must be positive")
  }
})
if err := positive.Set(-1); err != nil {
  panic(err) // must be positive
}

Then, bound widgets could simply pass through the validator on their binding.

E.g:

e := widget.NewEntryWithData(str)
e.SetText("bar")
if err := e.Validate(); err != nil {
  panic(err) // value too short
}

e.Bind(binding.IntToString(in))
e.SetText("-1")
if err := e.Validate(); err != nil {
  panic(err) // must be positive
}

Contributor guide