Components
Components approach is very common for modern web frameworks. It's not very popular in template engines. Even more, in most cases you can't define own functionality for each component. Kyoto library tries to combine this approach with template engines.
To define a component, we are using core receiver, just like we did with pages.
package main
import (
"net/http"
"encoding/json"
"github.com/kyoto-framework/kyoto"
"github.com/kyoto-framework/kyoto/lifecycle"
)
func ComponentUUID(core *kyoto.Core) {
lifecycle.Init(core, func() {
core.State.Set("UUID", "")
})
lifecycle.Async(core, func() error {
resp, _ := http.Get("http://httpbin.org/uuid")
data := map[string]string{}
json.NewDecoder(resp.Body).Decode(&data)
c.State.Set("UUID", data["uuid"])
return nil
})
}
{{ define "ComponentUUID" }}
<div>
UUID: {{ .UUID }}
</div>
{{ end }}
And now let's attach this component to the page multiple times.
...
func PageIndex(core *kyoto.Core) {
lifecycle.Init(core, func() {
core.Component("UUID1", ComponentUUID)
core.Component("UUID2", ComponentUUID)
})
...
}
...
{{ template "ComponentUUID" .UUID1 }}
{{ template "ComponentUUID" .UUID2 }}
...
Here you can see multiple things:
- Component definition
- Component template
- Component attaching to page
Our component just defines 2 lifecycle functions: init with setting empty state and async with getting UUID from httpbin.org. Lifecycle functionality will be described in a "Lifecycle" documentation category.
To define a component template, we are using define
template function.
Please note, definition name must to be the same as a component name.
Next thing in this list is creating a component instance and attaching to a page.
To do this, we are using core.Component
function.
To render attached component, we are using built-in template
function.
As an alternative, you can use render
function to render your component.
In this way, you can ommit specifying template name and just pass component instance.
Also, this approach opens up an option to use alternative rendering, described in
Features • Alternative rendering documentation category
...
{{ render .UUID1 }}
{{ render .UUID2 }}
...
To create a parameterized component, you can use a wrapped core receiver.
func ComponentFoo(param1, param2 string) func(*kyoto.Core) {
return func(core *kyoto.Core) {
...
}
}
Attach it to a page in the same way, but with a call.
core.Component("Foo", ComponentFoo("param1", "param2"))