mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] router: update app if parameterized route changes
This commit is contained in:
@@ -283,9 +283,7 @@ QWeb.addDirective({
|
|||||||
}
|
}
|
||||||
if (shouldWarn) {
|
if (shouldWarn) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Directive t-foreach should always be used with a t-key! (in template: '${
|
`Directive t-foreach should always be used with a t-key! (in template: '${ctx.templateName}')`
|
||||||
ctx.templateName
|
|
||||||
}')`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
nodeCopy.removeAttribute("t-foreach");
|
nodeCopy.removeAttribute("t-foreach");
|
||||||
|
|||||||
@@ -230,9 +230,7 @@ QWeb.addDirective({
|
|||||||
ctx.addLine(`const slot${slotKey} = this.slots[context.__owl__.slotId + '_' + '${value}'];`);
|
ctx.addLine(`const slot${slotKey} = this.slots[context.__owl__.slotId + '_' + '${value}'];`);
|
||||||
ctx.addIf(`slot${slotKey}`);
|
ctx.addIf(`slot${slotKey}`);
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`slot${slotKey}(context.__owl__.parent, Object.assign({}, extra, {parentNode: c${
|
`slot${slotKey}(context.__owl__.parent, Object.assign({}, extra, {parentNode: c${ctx.parentNode}, vars: extra.vars, parent: owner}));`
|
||||||
ctx.parentNode
|
|
||||||
}, vars: extra.vars, parent: owner}));`
|
|
||||||
);
|
);
|
||||||
ctx.closeIf();
|
ctx.closeIf();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+3
-9
@@ -1,6 +1,7 @@
|
|||||||
import { EventBus } from "../core/event_bus";
|
import { EventBus } from "../core/event_bus";
|
||||||
import { h, patch, VNode } from "../vdom/index";
|
import { h, patch, VNode } from "../vdom/index";
|
||||||
import { Context } from "./context";
|
import { Context } from "./context";
|
||||||
|
import { shallowEqual } from "../utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owl QWeb Engine
|
* Owl QWeb Engine
|
||||||
@@ -92,14 +93,7 @@ const UTILS: Utils = {
|
|||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
},
|
},
|
||||||
shallowEqual(p1, p2) {
|
shallowEqual
|
||||||
for (let k in p1) {
|
|
||||||
if (p1[k] !== p2[k]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseXML(xml: string): Document {
|
function parseXML(xml: string): Document {
|
||||||
@@ -212,7 +206,7 @@ export class QWeb extends EventBus {
|
|||||||
* template, with the name given by the t-name attribute.
|
* template, with the name given by the t-name attribute.
|
||||||
*/
|
*/
|
||||||
addTemplates(xmlstr: string | Document) {
|
addTemplates(xmlstr: string | Document) {
|
||||||
const doc = typeof xmlstr === 'string' ? parseXML(xmlstr) : xmlstr;
|
const doc = typeof xmlstr === "string" ? parseXML(xmlstr) : xmlstr;
|
||||||
const templates = doc.getElementsByTagName("templates")[0];
|
const templates = doc.getElementsByTagName("templates")[0];
|
||||||
if (!templates) {
|
if (!templates) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Env } from "../component/component";
|
|||||||
import { QWeb } from "../qweb/index";
|
import { QWeb } from "../qweb/index";
|
||||||
import { makeDirective } from "./directive";
|
import { makeDirective } from "./directive";
|
||||||
import { LINK_TEMPLATE, LINK_TEMPLATE_NAME } from "./Link";
|
import { LINK_TEMPLATE, LINK_TEMPLATE_NAME } from "./Link";
|
||||||
|
import { shallowEqual } from "../utils";
|
||||||
|
|
||||||
type NavigationGuard = (info: {
|
type NavigationGuard = (info: {
|
||||||
env: Env;
|
env: Env;
|
||||||
@@ -111,6 +112,7 @@ export class Router {
|
|||||||
async navigate(to: Destination): Promise<boolean> {
|
async navigate(to: Destination): Promise<boolean> {
|
||||||
const path = this.destToPath(to);
|
const path = this.destToPath(to);
|
||||||
const initialName = this.currentRouteName;
|
const initialName = this.currentRouteName;
|
||||||
|
const initialParams = this.currentParams;
|
||||||
const result = await this.matchAndApplyRules(path);
|
const result = await this.matchAndApplyRules(path);
|
||||||
if (result.type === "match") {
|
if (result.type === "match") {
|
||||||
const finalPath = this.routeToPath(result.route, result.params);
|
const finalPath = this.routeToPath(result.route, result.params);
|
||||||
@@ -121,7 +123,9 @@ export class Router {
|
|||||||
this.currentRoute = null;
|
this.currentRoute = null;
|
||||||
this.currentParams = null;
|
this.currentParams = null;
|
||||||
}
|
}
|
||||||
if (this.currentRouteName !== initialName) {
|
const didChange =
|
||||||
|
this.currentRouteName !== initialName || !shallowEqual(this.currentParams, initialParams);
|
||||||
|
if (didChange) {
|
||||||
this.env.qweb.forceUpdate();
|
this.env.qweb.forceUpdate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ export function makeDirective(env: RouterEnv) {
|
|||||||
// make new t t-component element
|
// make new t t-component element
|
||||||
const comp = node.ownerDocument.createElement("t");
|
const comp = node.ownerDocument.createElement("t");
|
||||||
comp.setAttribute("t-component", "__component__" + route.name);
|
comp.setAttribute("t-component", "__component__" + route.name);
|
||||||
comp.setAttribute(first ? "t-if" : "t-elif", `env.router.currentRouteName === '${route.name}'`);
|
comp.setAttribute(
|
||||||
|
first ? "t-if" : "t-elif",
|
||||||
|
`env.router.currentRouteName === '${route.name}'`
|
||||||
|
);
|
||||||
first = false;
|
first = false;
|
||||||
for (let param of route.params) {
|
for (let param of route.params) {
|
||||||
comp.setAttribute(param, `env.router.currentParams.${param}`);
|
comp.setAttribute(param, `env.router.currentParams.${param}`);
|
||||||
|
|||||||
@@ -95,3 +95,12 @@ export function debounce(func: Function, wait: number, immediate?: boolean): Fun
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shallowEqual(p1, p2): boolean {
|
||||||
|
for (let k in p1) {
|
||||||
|
if (p1[k] !== p2[k]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,18 @@ describe("router miscellaneous", () => {
|
|||||||
]);
|
]);
|
||||||
}).toThrow(`Invalid destination: {"abc":"hey"}`);
|
}).toThrow(`Invalid destination: {"abc":"hey"}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("navigate to same route but with different params should trigger update", async () => {
|
||||||
|
router = new TestRouter(env, [{ name: "users", path: "/users/{{id}}" }]);
|
||||||
|
env.qweb.forceUpdate = jest.fn();
|
||||||
|
await router.navigate({ to: "users", params: { id: 3 } });
|
||||||
|
expect(window.location.pathname).toBe("/users/3");
|
||||||
|
expect(env.qweb.forceUpdate).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await router.navigate({ to: "users", params: { id: 5 } });
|
||||||
|
expect(window.location.pathname).toBe("/users/5");
|
||||||
|
expect(env.qweb.forceUpdate).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("routeToPath", () => {
|
describe("routeToPath", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user