github.com/vugu/vugu@v0.3.5/vgform/select.go (about) 1 package vgform 2 3 import ( 4 "errors" 5 6 "github.com/vugu/vugu" 7 ) 8 9 // Select wraps an HTML select element. 10 // 11 // For clarity in naming: The word "value" refers to the value 12 // of the currently selected option. The word "key" refers to 13 // the text inside the value attribute of an option tag, and the 14 // word "text" refers to the HTML content of an option tag, i.e. 15 // `<option value="some-key">some text</option>`. 16 // 17 // The Value field is a StringValuer which is used to get the current 18 // value upon render, and update it when changed. 19 // The StringPtr type provides a simple adapter for *string. 20 // 21 // NOTE: When slots are supported this will be updated to support 22 // providing your own option tags so you can do things like 23 // option groups. 24 // 25 // For the common case of simple lists of texts, set the Options 26 // as appropriate. See SliceOptions and MapOptions 27 // for convenient adapters for []string and map[string]string. 28 type Select struct { 29 Value StringValuer // get/set the currently selected value 30 // TODO: should we also just make a ValuePtr *string - which would let people 31 // do :ValuePtr="&c.SomeRegularString" - seems like some people will want the convenience 32 // TODO: multiple (will need a new field and a new type, StringSliceValuer?) 33 34 Options Options // provide KeyLister and TextMapper in one 35 36 AttrMap vugu.AttrMap // regular HTML attributes like id and class 37 // TODO: might make sense to refactor this AttrMap thing to work well 38 // with SetAttributeInterface and AttributeLister/vg-attr - perhaps a slice of attributes 39 // is better and for vg-attr we just append to the slice and for the 40 // others we us SetAttributeInterace (or some variation that uses the same 41 // logic but works on an list of attributes.) A type AttributeList []VGAttribute 42 // might be in order. Refactor to separate vgnode package might be appropriate... 43 44 // el js.Value 45 keys []string 46 curVal string 47 } 48 49 func (c *Select) buildKeys() []string { 50 51 // if c.el.IsUndefined() { 52 // panic(errors.New("Select should have c.el set")) 53 // } 54 if c.Value == nil { 55 panic(errors.New("Select.Value must not be nil")) 56 } 57 if c.Options == nil { 58 panic(errors.New("Select.Options must not be nil (TODO: when slots are supported that will be allowed instead of Options)")) 59 } 60 61 c.keys = c.Options.KeyList() 62 c.curVal = c.Value.StringValue() 63 64 return c.keys 65 } 66 67 func (c *Select) isOptSelected(k string) bool { 68 return c.curVal == k 69 } 70 71 func (c *Select) optText(k string) string { 72 return c.Options.TextMap(k) 73 } 74 75 func (c *Select) handlePopulate() { 76 77 // var buf bytes.Buffer 78 // buf.Grow(len(`<option value=""></option>`) * len(c.keys) * 2) 79 // for _, k := range c.keys { 80 // buf.WriteString(`<option value="`) 81 // buf.WriteString(html.EscapeString(k)) 82 // buf.WriteString(`">`) 83 // buf.WriteString(html.EscapeString(c.Options.TextMap(k))) 84 // buf.WriteString(`</option>`) 85 // } 86 // c.el.Set("innerHTML", buf.String()) 87 88 // see if we need this... 89 // v := c.curVal 90 // idx := -1 91 // for i, k := range c.keys { 92 // if k == v { 93 // idx = i 94 // } 95 // } 96 97 // c.el.Set("selectedIndex", idx) 98 99 } 100 101 func (c *Select) handleChange(event vugu.DOMEvent) { 102 103 newVal := event.PropString("target", "value") 104 c.curVal = newVal // why not 105 c.Value.SetStringValue(newVal) 106 107 }