[IMP] tags: introduce xml tag

Big change! This commit introduces an xml function tag to easily define
inline templates.

This is a pretty big change toward single file owl components

Part of #284
This commit is contained in:
Géry Debongnie
2019-09-12 09:45:32 +02:00
parent cfc2fb2ba2
commit 9846b2e997
20 changed files with 381 additions and 310 deletions
+3 -3
View File
@@ -419,7 +419,7 @@ QWeb.addDirective({
const clone = <Element>node.cloneNode(true);
const slotNodes = clone.querySelectorAll("[t-set]");
const slotId = qweb.nextSlotId++;
const slotId = QWeb.nextSlotId++;
ctx.addLine(`w${componentID}.__owl__.slotId = ${slotId};`);
if (slotNodes.length) {
for (let i = 0, length = slotNodes.length; i < length; i++) {
@@ -428,7 +428,7 @@ QWeb.addDirective({
const key = slotNode.getAttribute("t-set")!;
slotNode.removeAttribute("t-set");
const slotFn = qweb._compile(`slot_${key}_template`, slotNode, ctx);
qweb.slots[`${slotId}_${key}`] = slotFn;
QWeb.slots[`${slotId}_${key}`] = slotFn;
}
}
if (clone.childNodes.length) {
@@ -437,7 +437,7 @@ QWeb.addDirective({
t.appendChild(child);
}
const slotFn = qweb._compile(`slot_default_template`, t, ctx);
qweb.slots[`${slotId}_default`] = slotFn;
QWeb.slots[`${slotId}_default`] = slotFn;
}
}
+2 -1
View File
@@ -10,6 +10,7 @@ import { QWeb } from "./qweb/index";
import { ConnectedComponent } from "./store/connected_component";
import { Store } from "./store/store";
import * as _utils from "./utils";
import * as _tags from "./tags";
import { Link } from "./router/Link";
import { RouteComponent } from "./router/RouteComponent";
import { Router } from "./router/Router";
@@ -20,7 +21,7 @@ export const core = { EventBus, Observer };
export const router = { Router, RouteComponent, Link };
export const store = { Store, ConnectedComponent };
export const utils = _utils;
export const tags = _tags;
export const __info__ = {};
Object.defineProperty(__info__, "mode", {
+3 -1
View File
@@ -227,7 +227,9 @@ QWeb.addDirective({
atNodeEncounter({ ctx, value }): boolean {
const slotKey = ctx.generateID();
ctx.rootContext.shouldDefineOwner = true;
ctx.addLine(`const slot${slotKey} = this.slots[context.__owl__.slotId + '_' + '${value}'];`);
ctx.addLine(
`const slot${slotKey} = this.constructor.slots[context.__owl__.slotId + '_' + '${value}'];`
);
ctx.addIf(`slot${slotKey}`);
ctx.addLine(
`slot${slotKey}.call(this, context.__owl__.parent, Object.assign({}, extra, {parentNode: c${ctx.parentNode}, vars: extra.vars, parent: owner}));`
+4 -3
View File
@@ -143,15 +143,16 @@ export class QWeb extends EventBus {
static TEMPLATES: { [name: string]: Template } = {};
static nextId: number = 1;
h = h;
// dev mode enables better error messages or more costly validations
static dev: boolean = false;
// slots contains sub templates defined with t-set inside t-component nodes, and
// are meant to be used by the t-slot directive.
slots = {};
nextSlotId = 1;
static slots = {};
static nextSlotId = 1;
// recursiveTemplates contains sub templates called with t-call, but which
// ends up in recursive situations. This is very similar to the slot situation,
+9 -9
View File
@@ -1,18 +1,18 @@
import { Component } from "../component/component";
import { xml } from "../tags";
import { Destination, RouterEnv } from "./Router";
export const LINK_TEMPLATE_NAME = "__owl__-router-link";
export const LINK_TEMPLATE = `
<a t-att-class="{'router-link-active': isActive }"
t-att-href="href"
t-on-click="navigate">
<t t-slot="default"/>
</a>`;
type Props = Destination;
export class Link<Env extends RouterEnv> extends Component<Env, Props, {}> {
static template = LINK_TEMPLATE_NAME;
static template = xml`
<a t-att-class="{'router-link-active': isActive }"
t-att-href="href"
t-on-click="navigate">
<t t-slot="default"/>
</a>
`;
href: string = this.env.router.destToPath(this.props);
async willUpdateProps(nextProps) {
+5 -5
View File
@@ -1,15 +1,15 @@
import { Component } from "../component/component";
import { xml } from "../tags";
export const ROUTE_COMPONENT_TEMPLATE_NAME = "__owl__-router-component";
export const ROUTE_COMPONENT_TEMPLATE = `
export class RouteComponent extends Component<any, {}, {}> {
static template = xml`
<t t-foreach="routes" t-as="route">
<t t-if="env.router.currentRouteName === route.name">
<t t-component="{{route.component}}" t-props="env.router.currentParams"/>
</t>
</t>`;
</t>
`;
export class RouteComponent extends Component<any, {}, {}> {
static template = ROUTE_COMPONENT_TEMPLATE_NAME;
routes: any[] = [];
constructor(parent, props) {
super(parent, props);
-6
View File
@@ -1,7 +1,5 @@
import { Env } from "../component/component";
import { QWeb } from "../qweb/index";
import { ROUTE_COMPONENT_TEMPLATE, ROUTE_COMPONENT_TEMPLATE_NAME } from "./RouteComponent";
import { LINK_TEMPLATE, LINK_TEMPLATE_NAME } from "./Link";
import { shallowEqual } from "../utils";
type NavigationGuard = (info: {
@@ -84,10 +82,6 @@ export class Router {
this.routes[partialRoute.name] = partialRoute as Route;
this.routeIds.push(partialRoute.name);
}
// setup link and directive
env.qweb.addTemplate(LINK_TEMPLATE_NAME, LINK_TEMPLATE);
env.qweb.addTemplate(ROUTE_COMPONENT_TEMPLATE_NAME, ROUTE_COMPONENT_TEMPLATE);
}
//--------------------------------------------------------------------------
+28
View File
@@ -0,0 +1,28 @@
import { QWeb } from "./qweb/index";
/**
* Owl Tags
*
* We have here a (very) small collection of tag functions:
*
* - xml
*
* The plan is to add a few other tags such as css, globalcss.
*/
/**
* XML tag helper for defining templates. With this, one can simply define
* an inline template with just the template xml:
* ```js
* class A extends Component {
* static template = xml`<div>some template</div>`;
* }
* ```
*/
export function xml(strings) {
const name = `__template__${QWeb.nextId++}`;
QWeb.registerTemplate(name, strings[0]);
return name;
}