mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] component: add static css support for sub components
part of issue #80
This commit is contained in:
+29
-8
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Example](#example)
|
- [Example](#example)
|
||||||
- [Templates](#templates)
|
- [Composition](#composition)
|
||||||
- [Reference](#reference)
|
- [Reference](#reference)
|
||||||
- [Properties](#properties)
|
- [Properties](#properties)
|
||||||
- [Methods](#methods)
|
- [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
|
is certainly encouraged. The state object is [observed](observer.md), and any
|
||||||
change to it will cause a rerendering.
|
change to it will cause a rerendering.
|
||||||
|
|
||||||
## Templates
|
## Composition
|
||||||
|
|
||||||
The example above shows a QWeb template with a `t-on-click` directive. Widget
|
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:
|
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:
|
widgets:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div>
|
<div t-name="parent">
|
||||||
<span>some text</span>
|
<span>some text</span>
|
||||||
<t t-widget="MyWidget" t-props="{info: 13}">
|
<t t-widget="MyWidget" t-props="{info: 13}">
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the template create a widget MyWidget just after the span. See
|
```js
|
||||||
the [QWeb](qweb.md) documentation for more information on the `t-widget` directive.
|
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
|
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.
|
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
|
||||||
|
<div t-name="parent">
|
||||||
|
<t t-widget="MyWidget" class="someClass" style="font-weight:bold;" t-props="{info: 13}">
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
An Owl component is a small class which represent a widget or some UI element.
|
An Owl component is a small class which represent a widget or some UI element.
|
||||||
|
|||||||
+14
-1
@@ -1212,8 +1212,21 @@ const widgetDirective: Directive = {
|
|||||||
finalizeWidgetCode += `;delete context.refs[${refKey}]`;
|
finalizeWidgetCode += `;delete context.refs[${refKey}]`;
|
||||||
}
|
}
|
||||||
ctx.addIf(`isNew${widgetID}`);
|
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(
|
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
|
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;});`
|
}[_${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;});`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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 = `
|
||||||
|
<div>
|
||||||
|
<t t-widget="child" class="a b"/>
|
||||||
|
</div>`;
|
||||||
|
widgets = { child: Child };
|
||||||
|
}
|
||||||
|
class Child extends Widget {
|
||||||
|
inlineTemplate = `<div class="c"/>`
|
||||||
|
}
|
||||||
|
const widget = new ParentWidget(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toBe(`<div><div class="c a b"></div></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("style is properly added on widget root el", async () => {
|
||||||
|
class ParentWidget extends Widget {
|
||||||
|
inlineTemplate = `
|
||||||
|
<div>
|
||||||
|
<t t-widget="child" style="font-weight: bold;"/>
|
||||||
|
</div>`;
|
||||||
|
widgets = { child: Widget };
|
||||||
|
}
|
||||||
|
const widget = new ParentWidget(env);
|
||||||
|
await widget.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toBe(`<div><div style="font-weight: bold;"></div></div>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("other directives with t-widget", () => {
|
describe("other directives with t-widget", () => {
|
||||||
test("t-on works as expected", async () => {
|
test("t-on works as expected", async () => {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user