hexops / vecty

Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.
BSD 3-Clause "New" or "Revised" License
2.79k stars 144 forks source link

prop.Value("") does not produce the correct html on first render #299

Open VinceJnz opened 2 years ago

VinceJnz commented 2 years ago

These do not produce the correct html on first render. They should add value="" to the select options element but they don't initially do it.

prop.Value("") vecty.Property("value", "")

I am using this as a workaround. vecty.Attribute("value", "")

The problem this causes is that when the select item is used in a form and is specified as required, the form validation does not work unless the first option has value=""

You can see the impact here in the "try it yourself" page https://www.w3schools.com/tags/att_select_required.asp

This is what should be produced

<form>
  <select id="Select option" required="">
      <option value="" selected="true">Select option</option>
      <option value="1">Test 1</option>
      <option value="2">Test 2</option>
      <option value="3">Test 3</option>
      <option value="4">Test etc...</option>
  </select>
</form>

This is what is initially produced

<form>
  <select id="Select option" required="">
      <option selected="true">Select option</option>
      <option value="1">Test 1</option>
      <option value="2">Test 2</option>
      <option value="3">Test 3</option>
      <option value="4">Test etc...</option>
  </select>
</form>

This is an example of the code I am using to produce the html


type ItemView struct { //ItemView
    vecty.Core

    Index    int               `vecty:"prop"`
    ID       int64             `vecty:"prop"`
    Item     *ItemStruct       `vecty:"prop"`
    Selected bool              `vecty:"prop"`
    Disabled bool              `vecty:"prop"`
}

func (p *ItemView) Render() vecty.ComponentOrHTML {
  if p.Item == nil {
      return elem.Option(
          vecty.Markup(
              //prop.Value(""), //doesn't work
              //vecty.Property("value", ""), //doesn't work
              vecty.Attribute("value", ""), //work-around for the above
              vecty.MarkupIf(p.Selected, vecty.Attribute("selected", true)),
              prop.Disabled(p.Disabled),
          ),
          vecty.Text("Select option"),
      )
  } else {
      return elem.Option(
          vecty.Markup(
              prop.Value(strconv.FormatInt(p.ID, 10)),
              vecty.MarkupIf(p.Selected, vecty.Attribute("selected", true)),
              prop.Disabled(p.Disabled),
          ),
          //vecty.Text(text),
          vecty.Text(p.Item.Name+" ("+p.Item.Description+")"),
      )
  }
}
type ListView struct {
    vecty.Core

    Label            string                 `vecty:"prop"`
    ValueID          *int64                 `vecty:"prop"`
    Required         bool                   `vecty:"prop"`
}

func (p *ListView) Render() vecty.ComponentOrHTML {
  var items vecty.List
  items = append(items, &ItemView{Index: -1, ID: 0, Selected: (*p.ValueID == 0), Disabled: false})

  for i, item := range MyItems {
    items = append(items, &ItemView{Index: i, ID: item.ID, Item: item, Selected: (*p.ValueID == item.ID), Disabled: false})
  }

  return elem.Div(
      elem.Label(
          vecty.Markup(
              prop.For(p.Label),
          ),
          vecty.Text(p.Label),
      ),
      elem.Select(
          vecty.Markup(
              prop.ID(p.Label),
              event.Change(p.onChange),
              vecty.MarkupIf(p.Required,
                  vecty.Property("required", true),
              ),
          ),
          items,
      ),
  )
}