Open 030 opened 5 years ago
@030 Wow, that was quick. I've only just started to put some of the effort online, but welcome! How did you find this project if I may ask?
Unfortunately, the wirebase/wire
cli is currently not very useful without the Go library that goes with it. The library is still in the works and I only expect it to be online in a couple of months but maybe you're interested giving your opinion general idea? The concept is this:
Render(m wb.Msg)
, 'Subscribe()and
Update()`. Each returns , declaratively, how the component should function and visualise.Render()
returns a wb.View
type that describes how the component should look, effectively HTML but we use generated go functions to make it expressive, type-safe and formatted by gofmt. The method receiver of Render()
is not passed as a pointer as the state should not be muted in the render method.Update(m wb.Msg)
is passed "Messages" (more on that later) and should update the fields
(state) of the component. These fields can be used in the Render()
method to display the component in a different way. As such the update method is the only method of the three that
has its receiver passed as a pointer as its sole job is to update the state.Navigate
message. This message will always be sent to the application first and should be delegated throughout the whole component tree./foo/bar.txt
, which component can assert to determine what html they would like to render. A Router library is shipped with the Wirebase library to make this easy.Subscribe()
method allows for defining event listeners that will trigger the sending of custom messages to the application.So how does this enable dynamic, static and single-page apps?
http.Handler
the component tree will be sent the Navigate message (see above) based on the http.Request
url path, and the server will ask all components to render their view. This is then send as the http.Response
body. Subscribe()
method to subcribe to events from the DOM, which are then passed to the Update()
method. Code example Your input is very valuable, so i'm curious to your impressions! I'm also located in the Netherlands so feel free to pm me.
package main
import (
"github.com/wirebase/wb"
"github.com/wirebase/wb/ajax"
// this package allows for expressive declaration of HTML
. "github.com/wirebase/wb/html"
)
// This example defines two message types, one to increment
// and one to decrement the counter.
type (
increment struct{}
decrement struct{}
saved struct{}
)
// Counter component has a very simple state, just a number
// to keep track of.
type Counter struct{ i int }
// NewCounter should initialize the component, in this case
// we start counting at 1
func NewCounter() *Counter {
return &Counter{i: 1}
}
// Update is called whenever an event is available for the
// application to handle. This event might come from a Cmd
// that was scheduled or an user interaction. Optionally, a
// command can be returned that will be executed after
// Rendering (e.g a Ajax request).
func (c *Counter) Update(m wb.Msg) wg.Cmd {
switch msg := m.(type) {
case increment:
c.i++
case decrement:
c.i--
case saved:
c.i = 0 //reset if saved
}
// lets imagine that we want to send an ajax request
// if someone manages to increment it to 10. The ajax
// request is send asyncronously by the runtime and
/// sends 'saved' message back to the application when
// its done.
if c.i >= 10 {
return ajax.NewRequest("post", "http://localhost/save_count", saved{})
}
return nil
}
// Render returns a declarative representation of the DOM
// that visually represents this component. The runtime
// will take care of removing and adding the necessary
// elements to present it to the user correctly. We use
// dot imports here to make defining the html more
// expressive.
func (c Counter) Render() wb.View {
return Div(C{"id": "my-counter"}
Button(c{"id": "inc"}),
Span(c.i), //show the currently counting method
Button(c{"id": "dec"}),
)
}
// Subscribe may define a set of subscriptions that will
// cause the sending of messages to the application. Subscribe
// is called after render and after execution of any
// commands. It may subcribe differently based on the
// component state.
func (c Counter) Subscribe() wb.Sub {
return wb.MultiSub(
// we use jqery like syntax to target elements in
// our view and declare listeners. Upon clicking
// the respective button the `inc` or `dec` message
// will be send to the update method.
wb.Listen("#inc", "onclick", inc{})
wb.Listen("#dec", "onclick", dec{})
)
}
@advanderveer Regarding:
How did you find this project if I may ask?
I am following you on Github.
Cool! What do you think of the concept?
I like the idea. Could you describe in the readme how to get started? Perhaps you could add an example project?