dojo dragon main logo

Setting a Widget's Properties

A widget's properties are exposed from a custom element automatically as either attributes, events, or properties.

The following EmailSignup widget contains several different property types.

src/widgets/EmailSignup.tsx

import { tsx, create } from '@dojo/framework/core/vdom';
import * as css from './styles/EmailSignup.m.css';
import icache from '@dojo/framework/core/middleware/icache';

export interface EmailSignupProperties {
    title?: string;
    onSignUp?: () => void;
    signUpBonusDate?: Date;
    successMessages?: string[];
}

function randomEntry(arr: string[]) {
    return arr[Math.floor(Math.random() * arr.length)];
}

const factory = create({ icache }).properties<EmailSignupProperties>();

export default factory(function EmailSignup({ middleware: { icache }, properties }) {
    const { title, signUpBonusDate, successMessages } = properties();

    const signedUp = icache.getOrSet('signedUp', false);
    const signUp = () => {
        const { onSignUp } = properties();

        // post email address to a server
        icache.set('signedUp', true);
        icache.set('successMessage', successMessages ? randomEntry(successMessages) : 'Thank you for signing up!');
        onSignUp && onSignUp();
    };

    return (
        <div key="root" classes={css.root}>
            <div key="title" classes={css.title}>
                {title || 'Subscribe Now'}
            </div>
            {signedUp ? (
                <div key="confirmation" classes={css.thanks}>
                    {icache.get('successMessage')}
                </div>
            ) : (
                <div key="signup" classes={css.signup}>
                    {signUpBonusDate && <div>Sign up by {signUpBonusDate.toLocaleDateString()}</div>}
                    <input type="text" />
                    <button onclick={signUp}>Sign Up</button>
                </div>
            )}
        </div>
    );
});

Attributes

string and object typed widget properties are automatically added as HTML attributes to your custom element. Continuing with the email subscription example, the title property ({ title?: string }) can be customized by adding a title attribute to the HTML. Since title is a string property, the value of the HTML attribute is used as the value of the title property with no transformation.

<ref-email-signup id="emailSignup" title="Subscribe to Our Newsletter"></ref-email-signup>

Other serializable properties, like arrays and configuration objects, can be set via HTML attributes by passing in serialized JSON. The sucessMessages property ({ successMessages?: string[] }) can be set by adding a successmessages attribute to the HTML.

<ref-email-signup
  id="emailSignup"
  title="Subscribe to Our Newsletter"
  successmessages='["Thanks!","Thank you for signing up","You are the best!"]'
></ref-email-signup>

Here, the value of the successmessages attribute will be deserialized and set as the successMessages property.

Note that if the attribute's value is not valid JSON, the property will not be set.

Events

Widget properties that start with on and have a function signature are exposed as events. The emitted event is the lower cased part of the property name without the "on." Listening for the onSignUp property ({ onSignUp?: () => void }) would look like this.

<script>
    emailSignup.addEventListener('signup', () => {
        // start confetti animation 🎉
    });
</script>

Properties

All non-event widget properties are automatically created as properties on the custom element. These properties can be fully controlled by JavaScript. In the email subscription widget, both the title and signUpBonusDate properties can be set programmatically as properties.

<script>
        const now = new Date();
        emailSignup.signUpBonusDate = new Date(
            now.getFullYear(),
            now.getMonth(),
            now.getDate() + 1
        );
    </script>