v0.5.7 beta
Back-end UI Framework

for feature-rich, secure, and fast web apps in Go

Tutorial

Title And Meta

Let’s add a dynamic title and metadata to our catalog page

1. Dynamic Title With Head Component

./catalog/page.templ

// converted templ to func equivalent
func (c *catalogPage) Head() templ.Component {
	// head component, takes path beam and function to derive HeadData
	return doors.Head(c.path, func(p Path) doors.HeadData {
		// no category selected
		if p.IsMain {
			return doors.HeadData{
				Title: "Catalog",
			}
		}
		cat, ok := driver.Cats.Get(p.CatId)
		// cannout find category
		if !ok {
			return doors.HeadData{
				Title: "Category Not Found",
			}
		}
		// category page
		if p.IsCat {
			return doors.HeadData{
				Title: cat.Name,
			}
		}
		item, ok := driver.Items.Get(p.ItemId)
		// cannot find item
		if !ok {
			return doors.HeadData{
				Title: "Item Not Found",
			}
		}
		return doors.HeadData{
			Title: item.Name,
		}
	})
}

That works and is totally okay. However, it’s not optimal because it runs the derive function on every path change, but not all path changes lead to a title change (for example, the page query parameter).

2. Optimize Update Strategy

// state that title depends on
type metaState struct {
	Cat  string
	Item int
}

func (c *catalogPage) Head() templ.Component {
	// derive new beam with metaState
	state := doors.NewBeam(c.path, func(p Path) metaState {
		if p.IsMain {
			return metaState{
				Cat:  "",
				Item: -1,
			}
		}
		if p.IsCat {
			return metaState{
				Cat:  p.CatId,
				Item: -1,
			}
		}
		return metaState{
			Cat:  p.CatId,
			Item: p.ItemId,
		}
	})
	// head component, takes path beam and function to derive HeadData
	return doors.Head(state, func(m metaState) doors.HeadData {
		// no category selected
		if m.Cat == "" {
			return doors.HeadData{
				Title: "Catalog",
			}
		}
		cat, ok := driver.Cats.Get(m.Cat)
		// cat not found
		if !ok {
			return doors.HeadData{
				Title: "Category Not Found",
			}
		}
		// category page
		if m.Item == -1 {
			return doors.HeadData{
				Title: cat.Name,
			}
		}
		item, ok := driver.Items.Get(m.Item)
		// item not found
		if !ok {
			return doors.HeadData{
				Title: "Item Not Found",
			}
		}
		return doors.HeadData{
			Title: item.Name,
		}
	})
}


3. Meta

If you want meta tags to update in response to a path change, include it in the HeadData

  /* ... */
  if m.Item == -1 {
    return doors.HeadData{
      Title: cat.Name,
      Meta: map[string]string{
        "description": cat.Desc,
      },
    }
  }
  /* ... */
  return doors.HeadData{
    Title: item.Name,
    Meta: map[string]string{
      "description": item.Desc,
    },
  }

If a meta tag was previously included in HeadData, but is absent in the new one, it will be removed from the page.