Use binding mechanism for the Pagination component
- Rename PaginationEvent to PaginateEvent - Add PaginationBinder interface
This commit is contained in:
parent
37d42e9a94
commit
c149bbfc06
@ -2,22 +2,22 @@ package navigation
|
||||
|
||||
import "github.com/vugu/vugu"
|
||||
|
||||
type PaginationEvent struct {
|
||||
type PaginateEvent struct {
|
||||
vugu.DOMEvent
|
||||
|
||||
Page int
|
||||
PaginationInfo // The current state of the pagination component.
|
||||
}
|
||||
|
||||
// PaginationHandler is the interface for things that can handle PaginationEvent.
|
||||
type PaginationHandler interface {
|
||||
PaginationHandle(event PaginationEvent)
|
||||
type PaginateHandler interface {
|
||||
PaginateHandle(event PaginateEvent)
|
||||
}
|
||||
|
||||
// PaginationFunc implements PaginationHandler as a function.
|
||||
type PaginationFunc func(event PaginationEvent)
|
||||
// PaginateFunc implements PaginateHandler as a function.
|
||||
type PaginateFunc func(event PaginateEvent)
|
||||
|
||||
// PaginationHandle implements the PaginationHandler interface.
|
||||
func (f PaginationFunc) PaginationHandle(event PaginationEvent) { f(event) }
|
||||
// PaginateHandle implements the PaginateHandler interface.
|
||||
func (f PaginateFunc) PaginateHandle(event PaginateEvent) { f(event) }
|
||||
|
||||
// assert PaginationFunc implements PaginationHandler.
|
||||
var _ PaginationHandler = PaginationFunc(nil)
|
||||
// assert PaginateFunc implements PaginateHandler.
|
||||
var _ PaginateHandler = PaginateFunc(nil)
|
||||
|
26
components/navigation/pagination-binder.go
Normal file
26
components/navigation/pagination-binder.go
Normal file
@ -0,0 +1,26 @@
|
||||
package navigation
|
||||
|
||||
// PaginationBinder is an interface that everything that every type that wants to bind to an pagination component must implement.
|
||||
type PaginationBinder interface {
|
||||
Page() int // Page returns the current page, as a 1-based index. A value of 0 means there is no active page.
|
||||
Pages() int // Pages returns the total number of pages.
|
||||
SetPage(page int) // SetPage changes the current page as a 1-based index. A value of 0 means there is no active page.
|
||||
}
|
||||
|
||||
// PaginationInfo implements the PaginationBinder interface and represents the current state of a pagination component.
|
||||
type PaginationInfo struct {
|
||||
CurrentPage int // The current page as a 1-based index. A value of 0 means there is no current page.
|
||||
TotalPages int // The number of total pages.
|
||||
}
|
||||
|
||||
func (p *PaginationInfo) Page() int {
|
||||
return p.CurrentPage
|
||||
}
|
||||
|
||||
func (p *PaginationInfo) Pages() int {
|
||||
return p.TotalPages
|
||||
}
|
||||
|
||||
func (p *PaginationInfo) SetPage(page int) {
|
||||
p.CurrentPage = page
|
||||
}
|
@ -10,10 +10,9 @@ type Pagination struct {
|
||||
|
||||
buttons []paginationButtonInfo
|
||||
|
||||
Page int `vugu:"data"`
|
||||
Pages int `vugu:"data"`
|
||||
Bind PaginationBinder
|
||||
|
||||
Pagination PaginationHandler // External handler that is called upon an event.
|
||||
Paginate PaginateHandler // External handler that is called upon an event.
|
||||
}
|
||||
|
||||
type paginationButtonInfo struct {
|
||||
@ -21,32 +20,55 @@ type paginationButtonInfo struct {
|
||||
Class string
|
||||
}
|
||||
|
||||
func (c *Pagination) Page() int {
|
||||
if c.Bind == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return c.Bind.Page()
|
||||
}
|
||||
|
||||
func (c *Pagination) Pages() int {
|
||||
if c.Bind == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return c.Bind.Pages()
|
||||
}
|
||||
|
||||
func (c *Pagination) handleClickPrev(event input.ClickEvent) {
|
||||
c.handleClickPage(event, c.Page-1)
|
||||
c.handleClickPage(event, c.Page()-1)
|
||||
}
|
||||
|
||||
func (c *Pagination) handleClickNext(event input.ClickEvent) {
|
||||
c.handleClickPage(event, c.Page+1)
|
||||
c.handleClickPage(event, c.Page()+1)
|
||||
}
|
||||
|
||||
func (c *Pagination) handleClickPage(event input.ClickEvent, page int) {
|
||||
if page <= 0 || page > c.Pages {
|
||||
pages := c.Pages()
|
||||
|
||||
if page <= 0 || page > pages {
|
||||
return
|
||||
}
|
||||
|
||||
if c.Pagination != nil {
|
||||
c.Pagination.PaginationHandle(PaginationEvent{
|
||||
if c.Bind != nil {
|
||||
c.Bind.SetPage(page)
|
||||
}
|
||||
|
||||
if c.Paginate != nil {
|
||||
c.Paginate.PaginateHandle(PaginateEvent{
|
||||
DOMEvent: event,
|
||||
Page: page,
|
||||
PaginationInfo: PaginationInfo{
|
||||
CurrentPage: page,
|
||||
TotalPages: pages,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Pagination) Init(ctx vugu.InitCtx) {
|
||||
c.Pages = 10
|
||||
}
|
||||
|
||||
func (c *Pagination) Compute(ctx vugu.ComputeCtx) {
|
||||
page, pages := c.Page(), c.Pages()
|
||||
|
||||
// Number of buttons around the current page.
|
||||
// Excluding first and last page.
|
||||
const AroundButtons = 2
|
||||
@ -60,15 +82,15 @@ func (c *Pagination) Compute(ctx vugu.ComputeCtx) {
|
||||
// Prepare buttons.
|
||||
buttons := [TotalButtons]paginationButtonInfo{
|
||||
0: {Page: 1},
|
||||
TotalButtons - 1: {Page: c.Pages},
|
||||
TotalButtons - 1: {Page: pages},
|
||||
}
|
||||
|
||||
startPage := 2
|
||||
if startPage < c.Page-AroundButtons {
|
||||
startPage = c.Page - AroundButtons
|
||||
if startPage < page-AroundButtons {
|
||||
startPage = page - AroundButtons
|
||||
}
|
||||
if startPage > c.Pages-DynamicButtons {
|
||||
startPage = c.Pages - DynamicButtons
|
||||
if startPage > pages-DynamicButtons {
|
||||
startPage = pages - DynamicButtons
|
||||
}
|
||||
|
||||
for i := 0; i < DynamicButtons; i++ {
|
||||
@ -79,13 +101,13 @@ func (c *Pagination) Compute(ctx vugu.ComputeCtx) {
|
||||
// pageCounter is used to check if pages are strictly monotonically increasing.
|
||||
buttonsFiltered := make([]paginationButtonInfo, 0, len(buttons))
|
||||
pageCounter := 0
|
||||
for _, page := range buttons {
|
||||
if pageCounter < page.Page && page.Page <= c.Pages {
|
||||
pageCounter = page.Page
|
||||
if page.Page == c.Page {
|
||||
page.Class = "d3c-button-highlight"
|
||||
for _, pageInfo := range buttons {
|
||||
if pageCounter < pageInfo.Page && pageInfo.Page <= pages {
|
||||
pageCounter = pageInfo.Page
|
||||
if pageInfo.Page == page {
|
||||
pageInfo.Class = "d3c-button-highlight"
|
||||
}
|
||||
buttonsFiltered = append(buttonsFiltered, page)
|
||||
buttonsFiltered = append(buttonsFiltered, pageInfo)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,15 +8,14 @@ import (
|
||||
)
|
||||
|
||||
type PageLayout struct {
|
||||
Page int `vugu:"data"`
|
||||
Pages int `vugu:"data"`
|
||||
Pagination navigation.PaginationInfo `vugu:"data"`
|
||||
}
|
||||
|
||||
func (c *PageLayout) Init(ctx vugu.InitCtx) {
|
||||
c.Pages = 10
|
||||
c.Pagination.CurrentPage = 2
|
||||
c.Pagination.TotalPages = 10
|
||||
}
|
||||
|
||||
func (c *PageLayout) handlePagination(event navigation.PaginationEvent) {
|
||||
log.Printf("Some page %v", event.Page)
|
||||
c.Page = event.Page
|
||||
func (c *PageLayout) handlePagination(event navigation.PaginateEvent) {
|
||||
log.Printf("Current pagination info: %v", event.PaginationInfo)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<h1>Layout</h1>
|
||||
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
|
||||
<h2>Items</h2>
|
||||
<navigation:Pagination :Page="c.Page" :Pages="c.Pages" @Pagination="c.handlePagination(event)"></navigation:Pagination>
|
||||
<navigation:Pagination :Bind="&c.Pagination" @Paginate="c.handlePagination(event)"></navigation:Pagination>
|
||||
<main:ComponentAddress Name="Max Mustermann" Street="Musterstraße 45" PostalCode="12345" City="Musterstadt" Country="Germany"></main:ComponentAddress>
|
||||
</layout:Container>
|
||||
</div>
|
||||
|
@ -28,7 +28,7 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
|
||||
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t"}
|
||||
vgparent.AppendChild(vgn)
|
||||
{
|
||||
vgcompKey := vugu.MakeCompKey(0x3467920B61750485^vgin.CurrentPositionHash(), vgiterkey)
|
||||
vgcompKey := vugu.MakeCompKey(0x60B66E06F722C68^vgin.CurrentPositionHash(), vgiterkey)
|
||||
// ask BuildEnv for prior instance of this specific component
|
||||
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*layout.Container)
|
||||
if vgcomp == nil {
|
||||
@ -62,7 +62,7 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
|
||||
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t"}
|
||||
vgparent.AppendChild(vgn)
|
||||
{
|
||||
vgcompKey := vugu.MakeCompKey(0x6A61FD21D9782C05^vgin.CurrentPositionHash(), vgiterkey)
|
||||
vgcompKey := vugu.MakeCompKey(0xD22F5BB58705C5DF^vgin.CurrentPositionHash(), vgiterkey)
|
||||
// ask BuildEnv for prior instance of this specific component
|
||||
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.Pagination)
|
||||
if vgcomp == nil {
|
||||
@ -71,9 +71,8 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
|
||||
vgin.BuildEnv.WireComponent(vgcomp)
|
||||
}
|
||||
vgin.BuildEnv.UseComponent(vgcompKey, vgcomp) // ensure we can use this in the cache next time around
|
||||
vgcomp.Page = c.Page
|
||||
vgcomp.Pages = c.Pages
|
||||
vgcomp.Pagination = navigation.PaginationFunc(func(event navigation.PaginationEvent) { c.handlePagination(event) })
|
||||
vgcomp.Bind = &c.Pagination
|
||||
vgcomp.Paginate = navigation.PaginateFunc(func(event navigation.PaginateEvent) { c.handlePagination(event) })
|
||||
vgout.Components = append(vgout.Components, vgcomp)
|
||||
vgn = &vugu.VGNode{Component: vgcomp}
|
||||
vgparent.AppendChild(vgn)
|
||||
@ -81,7 +80,7 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
|
||||
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t"}
|
||||
vgparent.AppendChild(vgn)
|
||||
{
|
||||
vgcompKey := vugu.MakeCompKey(0xD67C1752436E9AB1^vgin.CurrentPositionHash(), vgiterkey)
|
||||
vgcompKey := vugu.MakeCompKey(0xE6379FC706A49E07^vgin.CurrentPositionHash(), vgiterkey)
|
||||
// ask BuildEnv for prior instance of this specific component
|
||||
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*ComponentAddress)
|
||||
if vgcomp == nil {
|
||||
|
Loading…
Reference in New Issue
Block a user