Skip to main content

Properties

Define Properties​

Component takes an object literal containing properties and events for the component as second argument. Use the prop function to define properties and optionally pass a default value:

Component("simple-greeting", {
name: prop<string>("John"),
});

If you do not pass a default value, the property is undefined by default.

note

Property names must not start with on as that prefix is reserved for events.

danger

Property name must not collide with existing HTMLElement properties to avoid unexpected behavior.

Note that none of the properties are required to be set when constructing the component.

Access Properties​

In JS​

All properties can be accessed as actual class properties from the outside:

const el = new SimpleGreeting();
document.body.append(el);

console.log(el.name); // Prints default value "John"

el.name = "Jane"; // Component will now display "Hello, Jane!"
console.log(el.name); // Prints "Jane"

In JSX​

For reactivity in JSX templates, you need signals instead. You can get the signals of your properties in this.props:

<h1>Hello, {this.props.name}!</h1>

Set Properties​

In JS​

With a class instance, you can set properties directly:

const el = new SimpleGreeting();
document.body.append(el);

el.name = "Jane"; // Component will now display "Hello, Jane!"

These changes will be propagated through its corresponding signal this.props.name.

tip

It is generally discouraged to change properties from the inside of the component as it breaks the unidirectional data flow. Instead, you should use events to propagate changes upward.

In JSX​

Inside a JSX template, you can use JSX attributes to set properties, either using a static variable or a signal:

<SimpleGreeting name="John" />;
<SimpleGreeting name={this.props.name} />;

Attribute Association​

Define Attributes​

You can associate attributes with props by providing the attribute option of a prop:

Component("simple-greeting", {
name: prop<string>("John", {
attribute: {
// …
},
}),
});
HTML
<simple-greeting name="Jane"></simple-greeting>

By default all attribute changes will be propagated to the properties. If the corresponding attribute is not set on the element, the property will revert to the default value.

However, property changes will not be propagated back to attributes. You can stop propagation by setting the static option to true:

Component("simple-greeting", {
name: prop<string>("John", {
attribute: {
static: true,
},
}),
});

The attribute name will be the kebab-case version of the property name, e.g. a property named myName will be assigned the attribute name my-name. It's also possible to specify a custom attribute name:

Component("simple-greeting", {
name: prop<string>("John", {
attribute: {
name: "attr-name",
},
}),
});
HTML
<simple-greeting attr-name="Jane"></simple-greeting>
danger

Attribute names must not collide with existing HTMLElement attributes to avoid unexpected behavior.

The transform option can be used to transform attribute values when they are propagated to the property. This option is necessary if property type is not a string.

Component("simple-greeting", {
name: prop<string>("John", {
attribute: {
transform: (value) => value.toUpperCase(),
},
}),
});
HTML
<simple-greeting name="Jane"></simple-greeting>
<!-- Property `name` will be "JANE" -->

You can also use the shorthand notation:

Component("simple-greeting", {
name: prop<string>("John", {
attribute: (value) => value.toUpperCase(),
}),
});

String Attributes​

For string attributes, you can simply set the attribute option to String as a shorthand notation:

Component("simple-greeting", {
name: prop<string>("John", {
attribute: String,
}),
});
HTML
<simple-greeting name="Jane"></simple-greeting>
<!-- Property `name` will be "Jane" -->

Number Attributes​

For number attributes, you can set the attribute option to Number:

Component("simple-greeting", {
age: prop<number>(18, {
attribute: Number,
}),
});
HTML
<simple-greeting age="21"></simple-greeting>;
<!-- Property `age` will be 21 -->

Boolean Attributes​

For boolean attributes, it is recommended to set the default property value to false and to set transform to (value) => true:

Component("simple-greeting", {
active: prop<boolean>(false, {
attribute: () => true,
}),
});
HTML
<simple-greeting></simple-greeting>
<!-- Property `active` will be false -->
<simple-greeting active></simple-greeting>
<!-- Property `active` will be true -->
<simple-greeting active=""></simple-greeting>
<!-- Property `active` will be true -->
<simple-greeting active="false"></simple-greeting>
<!-- Property `active` will be true -->
note

This is counterintuitive, but this behavior is consistent with boolean attributes of standard HTML elements.

Children​

When using shadow DOM, you can allow light DOM children from the outside in your component. This allows techniques like slotting:

class SimpleGreetings extends Component("simple-greetings") {
render() {
return (
<>
Hello, <slot>John</slot>
</>
);
}
}

The following will print "Hello, Jane" where Jane is displayed in bold:

HTML
<simple-greeting>
<b>Jane</b>
</simple-greeting>
JSX
<SimpleGreeting>
<b>Jane</b>
</SimpleGreeting>