123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- <!DOCTYPE html>
- <html>
- <head>
- <title>Web Application - Page Func and Event Func - QOR5 Document</title>
- <meta name='description'>
- <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
- <base href='/docs/'>
- <link href='index.css' rel='stylesheet' type='text/css'>
- <script type='text/javascript' defer src='index.js'></script>
- </head>
- <body>
- <div id='app' v-cloak>
- <div v-init-context:vars='{hideAside: false}' class='flex h-screen'>
- <div class='flex-1 flex flex-col overflow-hidden'>
- <div class='flex h-full'>
- <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'>
- <div class='h-12'><search></search></div>
- <ul class='px-0 py-3 mx-0 text-base font-normal list-none text-gray-700'>
- <li class='m-0'>
- <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>
- </li>
- <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Getting Started</li>
- <li class='m-0'>
- <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>
- </li>
- <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Building Admin</li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Web Application</li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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's the whole house</a>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>UI Components</li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='m-0'>
- <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>
- </li>
- <li class='cursor-default px-4 py-1 truncate break-words w-64 m-0'>Appendix</li>
- <li class='m-0'>
- <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>
- </li>
- </ul>
- </aside>
- <main class='flex flex-col w-full bg-white overflow-x-hidden overflow-y-auto'>
- <div id='docContentBox' class='flex flex-row w-full'>
- <div class='flex flex-grow flex-col w-2/3'>
- <div class='flex flex-row'>
- <button @click='vars.hideAside = !vars.hideAside' class='w-12 h-12 p-4'>
- <div class='w-4 h-4 fill-current text-gray-300'>
- <?xml version="1.0" encoding="UTF-8"?>
- <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">
- <g id="surface1">
- <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 "/>
- </g>
- </svg>
- </div>
- </button>
- </div>
- <div id='docMainBox' class='px-16 pb-12 pt-4 overflow-auto'>
- <h1 class='mb-8'>Page Func and Event Func</h1>
- <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>
- <highlightjs :language='"go"' :code='"type PageFunc func(ctx *EventContext) (r PageResponse, err error)\ntype EventFunc func(ctx *EventContext) (r EventResponse, err error)\n"'></highlightjs>
- <p><code>web.Page(...)</code> converts multiple <code>EventFunc</code>s along with one <code>PageFunc</code> to a <code>http.Handler</code>,
- 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>
- <p>Here is a hello world with more interactions. User click the button will reload the page with latest time</p>
- <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>
- <div>
- <div class='demo'>
- <a href='/samples/hello_world_reload' target='_blank'>Check the demo</a>
- |
- <a href='https://github.com/qor5/docs/tree/main/docsrc/examples/e00_basics/hello-world-reload.go' target='_blank'>Source on GitHub</a>
- </div>
- </div>
- <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>
- <highlightjs :language='"go"' :code='"mux.Handle(\n\te00_basics.HelloWorldReloadPath,\n\te00_basics.HelloWorldReloadPB.Wrap(demoLayout),\n)"'></highlightjs>
- <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>
- <p>In case you don't know what is a http.Handler middleware,
- It's a function that takes http.Handler as input, might also with other parameters,
- And also return a new http.Handler,
- <a href="https://github.com/nytimes/gziphandler" rel="nofollow">gziphandler</a> is an example.</p>
- <p>But What the heck is <code>demoLayout</code> there?
- Well it's a <code>PageFunc</code> middleware. That takes an <code>PageFunc</code> as input,
- wrap it's <code>PageResponse</code> with layout html and return a new <code>PageFunc</code>.
- If you follow the code to write your own <code>PageFunc</code>,
- The button click might not work without this.
- Since there is no layout to import needed javascript to make this work.
- continue to next page to checkout how to add necessary javascript, css etc to make the demo work.</p>
- </div>
- </div>
- </div>
- <div class='font-medium text-base hidden xl:block text-gray-600 pt-4'>
- <div class='sticky top-4 w-52'>On This Page<toc></toc></div>
- </div>
- </div>
- <search-result></search-result></main>
- </div>
- </div>
- </div>
- </div>
- </body>
- </html>
|