Skip to content

Properties & State

George Treviranus edited this page Mar 24, 2022 · 12 revisions

Properties are the internal state mechanism in Bulba. Defining a property will always hook it into the render lifecycle, similar to how state works in React. Note that it's still possible to set your own properties in the constructor, and even create your own custom render behavior around them.

Define your properties using the static properties getter.

Each entry is the property name and its configuration object. Property names should always be camelCased.

Here's a quick example:

const countHTML = Symbol()

class MyCoolElement extends BulbaElement(Renderer) {
  static get properties() {
    return {
      propertyCount: {
        default: 2,
        type: "number",
        reflected: true,
      },
      [countHTML]: {
        default: (elem) => {
          const count = elem.getAttribute("property-count")
          return `<div>There's ${count} properties</div>`
        },
        type: "string",
        safe: true,
      },
    }
  }

  // ...
}

We've created two properties:

  • propertyCount: a string property (public)
  • countTag: a symbol property (private)

Use a symbol as the key to direct external access.

Property Configuration

Configuration is optional. Simply setting the property configuration to an empty object ({}) will be enough to upgrade a property into the render lifecycle.

Here are the available options:

default

Type: String, Function

The default value for the property.

If you use a callback, it receives just one argument: the this of your class (the HTML element itself). The function will be called only during the upgrade stage and NOT during subsequent re-renders.

type

Type: String

type should describe the data type for your property. Any time the property is set or changed, its type will be checked too. All primitive values are accepted.

Object shape / enum support TBD.

The development bundle will include component property validation. This feature is omitted in the production bundle.

Examples of types:

- string
- number
- object
- array
- function
- boolean

reflected

Type: Boolean
Default: false

If true, the property will reflect onto the host element as an attribute in kebab-case. E.g., myCoolProp becomes my-cool-prop.

Worth noting is that reflected properties double-bound. That's to say, if you update the attribute, the property will receive the value and re-render your component, and vice-versa. The only time this isn't true is if you set your property to undefined. Then, you need to set the property back to a non-undefined value to see an attribute value reflect into the property.

safe

Type: Boolean
Default: false

If you're using a string as the property value, this will tell Bulba to sanitize it and replace unsafe special characters with HTML-safe values.

Updating a Property

A property in Bulba is like any instance property on a JavaScript class. The difference is that a defined property hooks into the render lifecycle.

Every time an upgraded property changes it will trigger the following steps (in order):

  1. onPropertyChange
  2. onAttributeChange, if reflected
  3. Re-render to reflect new property / attribute changes into the DOM
  4. onUpdate

See lifecycle methods for how you can listen and respond to property/state changes.