Skip to content

Enable extra classes to be applied to child widgets #163

@agubler

Description

@agubler

Enhancement

Add an additional api to widgets that is structured like themes to allow for extra classes to be added
to a nested widget structure.

As a consumer applying extra classes to a widget is possible by passing an extraClasses property to the widget with the class name mapped to the widget's class that the the extra classes should be applied.

const props = {
    extraClasses: {
        root: 'my-extra-class'
    }
};

This simple API solves adding an extra class to a widget that is directly used but doesn't allow for extraClasses to be passed to child widgets that are used by the widget. Consider the following widget:

@theme(myWidgetCss)
class MyWidget extends Themed(WidgetBase) {
    protected render() {
        return v('div', { classes: [ this.theme(myWidgetCss.root) ] }, [
            w(ChildWidget, {})
        ]);
    }
}

There is no way that a consumer can pass extra classes to the ChildWidget rendered by MyWidget, even if MyWidget passed on extraClasses to ChildWidget there is no way to determine which of the extra classes should be applied to MyWidget or ChildWidget (as class names can clash, and often do with classes like .root).

With theming this is solved by widget classes being keyed by an identifier unique to the widget, such as:

const theme = {
    '@dojo/widgets/WidgetName': {
        root: 'class-name',
        other: 'other-class-name'
    }
};

Adopting an approach for passing extra classes would allow a consumer to create an extra classes object that could be passed to all child widgets and identify which classes should be applied to each widget:

// example widgets

@theme(childWidgetCss)
class ChildWidget extends Themed(WidgetBase) {
    protected render() {
        return v('div', { classes: [ this.theme(childWidgetCss.root) ] });
    }
}

@theme(myWidgetCss)
class MyWidget extends Themed(WidgetBase) {
    protected render() {
        const { classes } = this.properties;
        return v('div', { classes: [ this.theme(myWidgetCss.root) ] }, [
            // passing classes through to the child widget allows the consumer to 
            // apply extra classes.
            w(ChildWidget, { classes })
        ]);
    }
}

// usage

render() {
    const classes = {
        'widget-package-name/MyWidget': {
             root: 'extra-root-class-for-my-widget'
        },
        'widget-package-name/ChildWidget': {
            root: 'extra-root-class-for-child-widget'
        }
    }

    return w(MyWidget, { classes });
}

This would enable all widgets to have extra classes applied to them as along as the widget author passed the classes object to any child widgets used.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestnextIssue/Pull Request for the next major version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions