page-func-and-event-func.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Web Application - Page Func and Event Func - QOR5 Document</title>
  5. <meta name='description'>
  6. <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
  7. <base href='/docs/'>
  8. <link href='index.css' rel='stylesheet' type='text/css'>
  9. <script type='text/javascript' defer src='index.js'></script>
  10. </head>
  11. <body>
  12. <div id='app' v-cloak>
  13. <div v-init-context:vars='{hideAside: false}' class='flex h-screen'>
  14. <div class='flex-1 flex flex-col overflow-hidden'>
  15. <div class='flex h-full'>
  16. <aside v-show='!vars.hideAside' id='menuScroller' class='flex flex-col w-80 h-full bg-gray-50 border-r border-gray-200 overflow-y-auto'>
  17. <div class='h-12'><search></search></div>
  18. <ul class='px-0 py-3 mx-0 text-base font-normal list-none text-gray-700'>
  19. <li class='m-0'>
  20. <a href='index.html' id='index.html' onclick='window.storeMenuState("index.html")' class='inline-block px-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Introduction</a>
  21. </li>
  22. <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Getting Started</li>
  23. <li class='m-0'>
  24. <a href='getting-started/one-minute-quick-start.html' id='getting-started/one-minute-quick-start.html' onclick='window.storeMenuState("getting-started/one-minute-quick-start.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>1 Minute Quick Start</a>
  25. </li>
  26. <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Building Admin</li>
  27. <li class='m-0'>
  28. <a href='basics/listing.html' id='basics/listing.html' onclick='window.storeMenuState("basics/listing.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Listing</a>
  29. </li>
  30. <li class='m-0'>
  31. <a href='basics/filter.html' id='basics/filter.html' onclick='window.storeMenuState("basics/filter.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Filters</a>
  32. </li>
  33. <li class='m-0'>
  34. <a href='presets-guide/editing-customizations.html' id='presets-guide/editing-customizations.html' onclick='window.storeMenuState("presets-guide/editing-customizations.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Editing</a>
  35. </li>
  36. <li class='m-0'>
  37. <a href='basics/brand.html' id='basics/brand.html' onclick='window.storeMenuState("basics/brand.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Brand</a>
  38. </li>
  39. <li class='m-0'>
  40. <a href='basics/menu.html' id='basics/menu.html' onclick='window.storeMenuState("basics/menu.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Menu</a>
  41. </li>
  42. <li class='m-0'>
  43. <a href='presets-guide/detail-page-for-complex-object.html' id='presets-guide/detail-page-for-complex-object.html' onclick='window.storeMenuState("presets-guide/detail-page-for-complex-object.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Detailing</a>
  44. </li>
  45. <li class='m-0'>
  46. <a href='basics/layout.html' id='basics/layout.html' onclick='window.storeMenuState("basics/layout.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Layout</a>
  47. </li>
  48. <li class='m-0'>
  49. <a href='basics/login.html' id='basics/login.html' onclick='window.storeMenuState("basics/login.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Login</a>
  50. </li>
  51. <li class='m-0'>
  52. <a href='presets-guide/permissions.html' id='presets-guide/permissions.html' onclick='window.storeMenuState("presets-guide/permissions.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Permissions</a>
  53. </li>
  54. <li class='m-0'>
  55. <a href='presets-guide/role.html' id='presets-guide/role.html' onclick='window.storeMenuState("presets-guide/role.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Role</a>
  56. </li>
  57. <li class='m-0'>
  58. <a href='basics/notification-center.html' id='basics/notification-center.html' onclick='window.storeMenuState("basics/notification-center.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Notification Center</a>
  59. </li>
  60. <li class='m-0'>
  61. <a href='basics/shortcut.html' id='basics/shortcut.html' onclick='window.storeMenuState("basics/shortcut.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Keyboard Shortcut</a>
  62. </li>
  63. <li class='m-0'>
  64. <a href='basics/confirm-dialog.html' id='basics/confirm-dialog.html' onclick='window.storeMenuState("basics/confirm-dialog.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Confirm Dialog</a>
  65. </li>
  66. <li class='m-0'>
  67. <a href='slug.html' id='slug.html' onclick='window.storeMenuState("slug.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Slug</a>
  68. </li>
  69. <li class='m-0'>
  70. <a href='seo.html' id='seo.html' onclick='window.storeMenuState("seo.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>SEO</a>
  71. </li>
  72. <li class='m-0'>
  73. <a href='activity-log.html' id='activity-log.html' onclick='window.storeMenuState("activity-log.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Activity Log</a>
  74. </li>
  75. <li class='m-0'>
  76. <a href='basics/worker.html' id='basics/worker.html' onclick='window.storeMenuState("basics/worker.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Worker</a>
  77. </li>
  78. <li class='m-0'>
  79. <a href='basics/l10n.html' id='basics/l10n.html' onclick='window.storeMenuState("basics/l10n.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Localization</a>
  80. </li>
  81. <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Web Application</li>
  82. <li class='m-0'>
  83. <a href='basics/page-func-and-event-func.html' id='basics/page-func-and-event-func.html' onclick='window.storeMenuState("basics/page-func-and-event-func.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-blue-500'>Page Func and Event Func</a>
  84. </li>
  85. <li class='m-0'>
  86. <a href='advanced-functions/the-go-html-builder.html' id='advanced-functions/the-go-html-builder.html' onclick='window.storeMenuState("advanced-functions/the-go-html-builder.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>The Go HTML builder</a>
  87. </li>
  88. <li class='m-0'>
  89. <a href='presets-guide/its-the-whole-house.html' id='presets-guide/its-the-whole-house.html' onclick='window.storeMenuState("presets-guide/its-the-whole-house.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Not just scaffolding, it&#39;s the whole house</a>
  90. </li>
  91. <li class='m-0'>
  92. <a href='vuetify-components/lazy-portals.html' id='vuetify-components/lazy-portals.html' onclick='window.storeMenuState("vuetify-components/lazy-portals.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Lazy Portals</a>
  93. </li>
  94. <li class='m-0'>
  95. <a href='basics/layout-function-and-page-injector.html' id='basics/layout-function-and-page-injector.html' onclick='window.storeMenuState("basics/layout-function-and-page-injector.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Layout Function and Page Injector</a>
  96. </li>
  97. <li class='m-0'>
  98. <a href='basics/switch-pages-with-push-state.html' id='basics/switch-pages-with-push-state.html' onclick='window.storeMenuState("basics/switch-pages-with-push-state.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Switch Pages with Push State</a>
  99. </li>
  100. <li class='m-0'>
  101. <a href='basics/reload-page-with-a-flash.html' id='basics/reload-page-with-a-flash.html' onclick='window.storeMenuState("basics/reload-page-with-a-flash.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Reload Page with a Flash</a>
  102. </li>
  103. <li class='m-0'>
  104. <a href='basics/partial-refresh-with-portal.html' id='basics/partial-refresh-with-portal.html' onclick='window.storeMenuState("basics/partial-refresh-with-portal.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Partial Refresh with Portal</a>
  105. </li>
  106. <li class='m-0'>
  107. <a href='basics/manipulate-page-url-in-event-func.html' id='basics/manipulate-page-url-in-event-func.html' onclick='window.storeMenuState("basics/manipulate-page-url-in-event-func.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Manipulate Page URL in Event Func</a>
  108. </li>
  109. <li class='m-0'>
  110. <a href='basics/summary-of-event-response.html' id='basics/summary-of-event-response.html' onclick='window.storeMenuState("basics/summary-of-event-response.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Summary of Event Response</a>
  111. </li>
  112. <li class='m-0'>
  113. <a href='basics/scope-component.html' id='basics/scope-component.html' onclick='window.storeMenuState("basics/scope-component.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Scope Component</a>
  114. </li>
  115. <li class='m-0'>
  116. <a href='basics/event-handling.html' id='basics/event-handling.html' onclick='window.storeMenuState("basics/event-handling.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Event Handling</a>
  117. </li>
  118. <li class='m-0'>
  119. <a href='basics/form-handling.html' id='basics/form-handling.html' onclick='window.storeMenuState("basics/form-handling.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Form Handling</a>
  120. </li>
  121. <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>UI Components</li>
  122. <li class='m-0'>
  123. <a href='vuetify-components/basic-inputs.html' id='vuetify-components/basic-inputs.html' onclick='window.storeMenuState("vuetify-components/basic-inputs.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Basic Inputs</a>
  124. </li>
  125. <li class='m-0'>
  126. <a href='vuetify-components/a-taste-of-using-vuetify-in-go.html' id='vuetify-components/a-taste-of-using-vuetify-in-go.html' onclick='window.storeMenuState("vuetify-components/a-taste-of-using-vuetify-in-go.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>A Taste of using Vuetify in Go</a>
  127. </li>
  128. <li class='m-0'>
  129. <a href='vuetify-components/linkage-select.html' id='vuetify-components/linkage-select.html' onclick='window.storeMenuState("vuetify-components/linkage-select.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Linkage Select</a>
  130. </li>
  131. <li class='m-0'>
  132. <a href='vuetify-components/auto-complete.html' id='vuetify-components/auto-complete.html' onclick='window.storeMenuState("vuetify-components/auto-complete.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Auto Complete</a>
  133. </li>
  134. <li class='m-0'>
  135. <a href='components-guide/composite-new-component-with-go.html' id='components-guide/composite-new-component-with-go.html' onclick='window.storeMenuState("components-guide/composite-new-component-with-go.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Composite new Component With Go</a>
  136. </li>
  137. <li class='m-0'>
  138. <a href='components-guide/integrate-a-heavy-vue-component.html' id='components-guide/integrate-a-heavy-vue-component.html' onclick='window.storeMenuState("components-guide/integrate-a-heavy-vue-component.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>Integrate a heavy Vue Component</a>
  139. </li>
  140. <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Appendix</li>
  141. <li class='m-0'>
  142. <a href='appendix/all-demo-examples.html' id='appendix/all-demo-examples.html' onclick='window.storeMenuState("appendix/all-demo-examples.html")' class='inline-block pl-10 pr-4 py-1 truncate break-words w-64 hover:text-blue-400 text-gray-700'>All Demo Examples</a>
  143. </li>
  144. </ul>
  145. </aside>
  146. <main class='flex flex-col w-full bg-white overflow-x-hidden overflow-y-auto'>
  147. <div id='docContentBox' class='flex flex-row w-full'>
  148. <div class='flex flex-grow flex-col w-2/3'>
  149. <div class='flex flex-row'>
  150. <button @click='vars.hideAside = !vars.hideAside' class='w-12 h-12 p-4'>
  151. <div class='w-4 h-4 fill-current text-gray-300'>
  152. <?xml version="1.0" encoding="UTF-8"?>
  153. <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
  154. <g id="surface1">
  155. <path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 2 12 L 2 11 L 14 11 L 14 12 Z M 2 8.5 L 2 7.5 L 14 7.5 L 14 8.5 Z M 2 5 L 2 4 L 14 4 L 14 5 Z M 2 5 "/>
  156. </g>
  157. </svg>
  158. </div>
  159. </button>
  160. </div>
  161. <div id='docMainBox' class='px-16 pb-12 pt-4 overflow-auto'>
  162. <h1 class='mb-8'>Page Func and Event Func</h1>
  163. <div class='border-t'><p><code>PageFunc</code> is used to build a web page, <code>EventFunc</code> is called when user interact with the page, For example button or link clicks.</p>
  164. <highlightjs :language='"go"' :code='"type PageFunc func(ctx *EventContext) (r PageResponse, err error)\ntype EventFunc func(ctx *EventContext) (r EventResponse, err error)\n"'></highlightjs>
  165. <p><code>web.Page(...)</code> converts multiple <code>EventFunc</code>s along with one <code>PageFunc</code> to a <code>http.Handler</code>,
  166. event func needs a name to be used by <code>web.POST().EventFunc(name).Go()</code> to attach to an html element that post http request to call the <code>EventFunc</code> when vue event like <code>@click</code> happens</p>
  167. <p>Here is a hello world with more interactions. User click the button will reload the page with latest time</p>
  168. <highlightjs :language='"go"' :code='"import (\n\t\"time\"\n\n\t\"github.com/qor5/web\"\n\t. \"github.com/theplant/htmlgo\"\n)\n\nfunc HelloWorldReload(ctx *web.EventContext) (pr web.PageResponse, err error) {\n\tpr.Body = Div(\n\t\tH1(\"Hello World\"),\n\t\tText(time.Now().Format(time.RFC3339Nano)),\n\t\tButton(\"Reload Page\").Attr(\"@click\", web.GET().\n\t\t\tEventFunc(reloadEvent).\n\t\t\tGo()),\n\t)\n\treturn\n}\n\nfunc update(ctx *web.EventContext) (er web.EventResponse, err error) {\n\ter.Reload = true\n\treturn\n}\n\nconst reloadEvent = \"reload\"\n\nvar HelloWorldReloadPB = web.Page(HelloWorldReload).\n\tEventFunc(reloadEvent, update)\n\nconst HelloWorldReloadPath = \"/samples/hello_world_reload\"\n"'></highlightjs>
  169. <div>
  170. <div class='demo'>
  171. <a href='/samples/hello_world_reload' target='_blank'>Check the demo</a>
  172. |
  173. <a href='https://github.com/qor5/docs/tree/main/docsrc/examples/e00_basics/hello-world-reload.go' target='_blank'>Source on GitHub</a>
  174. </div>
  175. </div>
  176. <p>Note that you have to mount the <code>web.Page(...)</code> instance to http.ServeMux with a path to be able to access the <code>PageFunc</code> in your browser, when mounting you can also wrap the <code>PageFunc</code> with middleware, which is <code>func(in PageFunc) (out PageFunc)</code> a func that take a page func and do some wrapping and return a new page func</p>
  177. <highlightjs :language='"go"' :code='"mux.Handle(\n\te00_basics.HelloWorldReloadPath,\n\te00_basics.HelloWorldReloadPB.Wrap(demoLayout),\n)"'></highlightjs>
  178. <p><code>wb.Page(...)</code> convert any <code>PageFunc</code> into <code>http.Handler</code>, outside you can wrap any middleware that can use on Go standard <code>http.Handler</code>.</p>
  179. <p>In case you don&#39;t know what is a http.Handler middleware,
  180. It&#39;s a function that takes http.Handler as input, might also with other parameters,
  181. And also return a new http.Handler,
  182. <a href="https://github.com/nytimes/gziphandler" rel="nofollow">gziphandler</a> is an example.</p>
  183. <p>But What the heck is <code>demoLayout</code> there?
  184. Well it&#39;s a <code>PageFunc</code> middleware. That takes an <code>PageFunc</code> as input,
  185. wrap it&#39;s <code>PageResponse</code> with layout html and return a new <code>PageFunc</code>.
  186. If you follow the code to write your own <code>PageFunc</code>,
  187. The button click might not work without this.
  188. Since there is no layout to import needed javascript to make this work.
  189. continue to next page to checkout how to add necessary javascript, css etc to make the demo work.</p>
  190. </div>
  191. </div>
  192. </div>
  193. <div class='font-medium text-base hidden xl:block text-gray-600 pt-4'>
  194. <div class='sticky top-4 w-52'>On This Page<toc></toc></div>
  195. </div>
  196. </div>
  197. <search-result></search-result></main>
  198. </div>
  199. </div>
  200. </div>
  201. </div>
  202. </body>
  203. </html>