Vugu Files - Markup (HTML/Go)

The Markup section is an element which has the HTML that is displayed for this file (each file is a "component", following the parlance of other UI libraries).

In addition to regular HTML, some specific attributes have special meaning in Vugu and allow you to introduce logic into your component's display.

Conditionals with vg-if

You can choose a condition for an element to be displayed using vg-if='condition'. The condition is regular Go code and during code generation is put directly between if and { in the resulting .go file. While the expression itself can be any valid Go code for an if statement, a common case is to reference a member variable of your Component's Data struct. For example:

<div>
    <p vg-if='data.ShowText'>
        Conditional text here.
    </p>
</div>

<script type="application/x-go">
type RootData struct { // component data for "root"
    ShowText bool
}
</script>

Loops with vg-for

Loops correspond directly to for blocks in Go code. All forms of loops are supported including the init; condition; post syntax as well as range expressions. For example:

<div>
    <p vg-for='i := 0; i < 10; i++'>
        <div vg-html="i"></div>
    </p>
</div>
<div>
    <p vg-for='_, item := range data.Items'>
        <div vg-html="item"></div>
    </p>
</div>

<script type="application/x-go">
type RootData struct { // component data for "root"
    Items []string
}
</script>

Note that the vg-html attribute outputs the value as HTML, using fmt.Sprint(), see below.

As a special case and for convenience, if the expression contains no whitespace it will be expanded to for key, value := range expr { _, _ = key, value; .... Example:

<div>
    <p vg-for='data.Items'>
        <div>
          Key: <span vg-html="key"></span>
          Value: <span vg-html="value"></span>
        </div>
    </p>
</div>

<script type="application/x-go">
type RootData struct { // component data for "root"
    Items []string
}
</script>

Raw HTML with vg-html

The vg-html attribute is used to output an expression as HTML into the contents of an element. (It corresponds to the innerHTML property.) The expression converted to a string using fmt.Sprint(). Example:

<div>
    <p vg-html='"<b>an HTML string</b>"'>
    <p vg-html='123'> <!-- will be output according to fmt.Sprint rules -->
    <p vg-html='html.EscapeString("escaping & arbitrary text is easy like so")'>
</div>

<script type="application/x-go">
import "html"
</script>

You may use variable names declared in earlier constructs (such as key or value from a for/range loop). Regular Go variable scoping rules apply, where each nested DOM element is equivalent to a Go { code block }.

Dynamic Attributes with :

The values of HTML attributes can be made dynamic and accept Go expressions. Dynamically changing attribute values has many uses such as applying CSS dynamically styles with the class attribute.

<div>
    <p :style='"background:"+data.BgColor'></p>
</div>

<script type="application/x-go">
type RootData struct {
  BgColor string // e.g. "blue"
}
</script>

You may use variable names declared in earlier constructs (such as key or value from a for/range loop). Regular Go variable scoping rules apply, where each nested DOM element is equivalent to a Go { code block }.

Note that in addition to the above use, dynamic attributes are frequently used in conjuction with components, where the attributes become properties that are passed into a component when it is instantiated. In this case, the attributes are not converted to strings but are kept as regular Go values (store as interface{}). See the Components page for more info.

DOM Events with @

Event handlers can be attached to HTML elements (à la addEventListener) using special attributes prefixed with an @ symbol.

The attribute name after the @ indicates the event name, e.g. "click". The attribute value must be a Go function/method call. Other Go statements are not currently allowed. The arguments to the function call can be anything valid in Go, including literals.

Note that these values must hash properly with ComputeHash(), as this is needed by Vugu to keep track of its events internally. Most primitive types that just store data are fine, but please, no channels.

You may use variable names declared in earlier constructs (such as key or value from a for/range loop). Regular Go variable scoping rules apply, where each nested DOM element is equivalent to a Go { code block }. The special variable event which is of type *vugu.DOMEvent can be used a placeholder and is replaced when the method is invoked with an appropriate event object. See DOM Events for more info. Example:

<div>
    <div vg-if='data.Show'>I am here!</div>
    <button @click='data.Toggle()'>Toggle me Silly</button>
</div>

<script type="application/x-go">
func (data *RootData) Toggle() { data.Show = !data.Show }
type RootData struct {
  Show bool
}
</script>

Special Variable Names

Several variable names have special meaning and are useful when writing .vugu files:

  • data - Refers to the instance of your Component. It is typically a struct pointer. This is the proper place to house the state of your component. By default this is an empty struct but it is common to create your own struct with the data you need on it. See more at Components
  • comp - Refers to the component type. Unless you write something specific for this it will be an empty struct. However it can be useful if you need to store configuration info that is determined at app startup and is the same for each instance of a component.
  • event - This is a placeholder for a *vugu.DOMEvent instance that is created when a DOM event is triggered and your handler is called. This also provides some other needed functionality such as the EventEnv, which is important for synchronizing goroutines that need to update data after an event completes. See more at DOM Events.
  • key and value - See section covering vg-for above. These are the default names used for implied range expressions.

Please note that variables that your code declares, e.g. in a vg-for loop, should not end with an underscore in order to avoid conflicting with generated code.