diff --git a/doc/component.md b/doc/component.md
index cba5b9c4..caf29ce2 100644
--- a/doc/component.md
+++ b/doc/component.md
@@ -4,7 +4,7 @@
- [Overview](#overview)
- [Example](#example)
-- [Templates](#templates)
+- [Composition](#composition)
- [Reference](#reference)
- [Properties](#properties)
- [Methods](#methods)
@@ -65,7 +65,7 @@ a state object is defined. It is not mandatory to use the state object, but it
is certainly encouraged. The state object is [observed](observer.md), and any
change to it will cause a rerendering.
-## Templates
+## Composition
The example above shows a QWeb template with a `t-on-click` directive. Widget
templates are standard [QWeb](qweb.md) templates, but with an extra directive:
@@ -73,18 +73,39 @@ templates are standard [QWeb](qweb.md) templates, but with an extra directive:
widgets:
```xml
-
- some text
-
-
+
+ some text
+
+
```
-In this example, the template create a widget MyWidget just after the span. See
-the [QWeb](qweb.md) documentation for more information on the `t-widget` directive.
+```js
+class ParentWidget extends owl.Component {
+ template = 'parent';
+ widgets = { MyWidget: MyWidget};
+ ...
+}
+```
+
+In this example, the `ParentWidget`'s template creates a widget `MyWidget` just
+after the span. See the [QWeb](qweb.md) documentation for more information on the
+`t-widget` directive.
Note that the rendering context for the template is the widget itself. This means
that the template can access `state`, `props`, `env`, or any methods defined in the widget.
+**CSS and style:** there is some specific support to allow the parent to declare
+additional css classes or style for the sub widget: css declared in `class`, `style`, `t-att-class` or `t-att-style` will be added to the
+root widget element.
+
+```xml
+
+
+
+```
+
+
+
## Reference
An Owl component is a small class which represent a widget or some UI element.
diff --git a/src/qweb.ts b/src/qweb.ts
index 8798e146..4b5b3c71 100644
--- a/src/qweb.ts
+++ b/src/qweb.ts
@@ -1212,8 +1212,21 @@ const widgetDirective: Directive = {
finalizeWidgetCode += `;delete context.refs[${refKey}]`;
}
ctx.addIf(`isNew${widgetID}`);
+ let createHook = "";
+ let classAttr = node.getAttribute("class");
+ let styleAttr = node.getAttribute("style");
+ if (classAttr || styleAttr) {
+ const classCode = classAttr
+ ? classAttr
+ .split(" ")
+ .map(c => `vn.elm.classList.add('${c}')`)
+ .join(";") + ";"
+ : "";
+ const styleCode = styleAttr ? `vn.elm.style = '${styleAttr}'` : "";
+ createHook = `vnode.data.hook = {create(_, vn){${classCode}${styleCode}}};`;
+ }
ctx.addLine(
- `def${defID} = def${defID}.then(vnode=>{let pvnode=h(vnode.sel, {key: ${templateID}});c${
+ `def${defID} = def${defID}.then(vnode=>{${createHook}let pvnode=h(vnode.sel, {key: ${templateID}});c${
ctx.parentNode
}[_${dummyID}_index]=pvnode;pvnode.data.hook = {insert(vn){let nvn=w${widgetID}._mount(vnode, vn.elm);pvnode.elm=nvn.elm;${refExpr}},remove(){${finalizeWidgetCode}},destroy(){${finalizeWidgetCode}}}; w${widgetID}.__owl__.pvnode = pvnode;});`
);
diff --git a/tests/component.test.ts b/tests/component.test.ts
index ce9ef951..0af094cc 100644
--- a/tests/component.test.ts
+++ b/tests/component.test.ts
@@ -1224,6 +1224,37 @@ describe("props evaluation (with t-props directive)", () => {
});
});
+describe("class and style attributes with t-widget", () => {
+ test("class is properly added on widget root el", async () => {
+ class ParentWidget extends Widget {
+ inlineTemplate = `
+
+
+
`;
+ widgets = { child: Child };
+ }
+ class Child extends Widget {
+ inlineTemplate = ``
+ }
+ const widget = new ParentWidget(env);
+ await widget.mount(fixture);
+ expect(fixture.innerHTML).toBe(``);
+ });
+
+ test("style is properly added on widget root el", async () => {
+ class ParentWidget extends Widget {
+ inlineTemplate = `
+
+
+
`;
+ widgets = { child: Widget };
+ }
+ const widget = new ParentWidget(env);
+ await widget.mount(fixture);
+ expect(fixture.innerHTML).toBe(``);
+ });
+});
+
describe("other directives with t-widget", () => {
test("t-on works as expected", async () => {
let n = 0;