page.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package e05_hello_customized_component
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/qor5/web"
  6. . "github.com/theplant/htmlgo"
  7. )
  8. type TagsInputBuilder struct {
  9. classNames []string
  10. selectedKeys []string
  11. options []*TagsInputOption
  12. }
  13. type TagsInputOption struct {
  14. Key string
  15. Label HTMLComponent
  16. }
  17. func TagsInput() (r *TagsInputBuilder) {
  18. r = &TagsInputBuilder{}
  19. return
  20. }
  21. func (b *TagsInputBuilder) Class(names ...string) (r *TagsInputBuilder) {
  22. b.classNames = names
  23. return b
  24. }
  25. func (b *TagsInputBuilder) Selected(keys []string) (r *TagsInputBuilder) {
  26. b.selectedKeys = keys
  27. return b
  28. }
  29. func (b *TagsInputBuilder) Options(options ...*TagsInputOption) (r *TagsInputBuilder) {
  30. b.options = options
  31. return b
  32. }
  33. func contains(k string, in []string) bool {
  34. for _, i := range in {
  35. if k == i {
  36. return true
  37. }
  38. }
  39. return false
  40. }
  41. func (b *TagsInputBuilder) MarshalHTML(ctx context.Context) (r []byte, err error) {
  42. // ui.Injector(ctx).PutScript(tagsInputScript)
  43. // ui.Injector(ctx).PutStyle(tagsInputStyles)
  44. selectedComps := []HTMLComponent{}
  45. optionComps := []HTMLComponent{}
  46. for _, op := range b.options {
  47. optionComps = append(optionComps, op.Label)
  48. if contains(op.Key, b.selectedKeys) {
  49. selectedComps = append(selectedComps, op.Label)
  50. }
  51. }
  52. root := Tag("tags-input").
  53. Class("tagsInput").
  54. Attr("v-slot", "{ parent }").
  55. Children(
  56. Div(
  57. Div().Class("tagsInputSelected").Children(
  58. selectedComps...,
  59. ),
  60. Tag("button").Text("Toggle").Attr("v-on:click", "parent.toggle()"),
  61. ),
  62. Div().
  63. Class("tagsInputOptions").
  64. Attr("v-bind:class", "{tagsInputOptionsOpen: parent.isOpen}").Children(
  65. optionComps...,
  66. ),
  67. )
  68. return root.MarshalHTML(ctx)
  69. }
  70. // const tagsInputScript = `
  71. // (window.__qor5VueComponentRegisters = (window.__qor5VueComponentRegisters || [])).push(function(Vue){
  72. // Vue.component("tags-input", {
  73. // data: function() {
  74. // return {
  75. // isOpen: false
  76. // };
  77. // },
  78. // methods: {
  79. // toggle: function() {
  80. // this.isOpen = !this.isOpen;
  81. // }
  82. // },
  83. // template: "<div><slot v-bind:parent='this'/></div>"
  84. // });
  85. // })
  86. // `
  87. //
  88. // const tagsInputStyles = `
  89. // .tagsInput .tagsInputOptions {
  90. // display: none;
  91. // }
  92. //
  93. // .tagsInput .tagsInputOptions.tagsInputOptionsOpen {
  94. // display: block;
  95. // }
  96. // `
  97. // Above is component code
  98. type mystate struct {
  99. Message string
  100. }
  101. func HelloCustomziedComponent(ctx *web.EventContext) (pr web.PageResponse, err error) {
  102. // s := ctx.StateOrInit(&mystate{}).(*mystate)
  103. opts := []*TagsInputOption{}
  104. for i := 1; i < 11; i++ {
  105. opts = append(opts, &TagsInputOption{
  106. Key: fmt.Sprint(i),
  107. Label: Div().Text(fmt.Sprintf("label %d", i)),
  108. })
  109. }
  110. pr.Body = Div(
  111. TagsInput().Selected([]string{"1", "2", "3"}).Options(opts...),
  112. Button("Refresh").Attr("@click",
  113. web.POST().EventFunc("refresh").Go(),
  114. ),
  115. )
  116. return
  117. }
  118. func reload(ctx *web.EventContext) (r web.EventResponse, err error) {
  119. r.Reload = true
  120. return
  121. }