[FIX] router: update app if parameterized route changes

This commit is contained in:
Géry Debongnie
2019-08-31 15:03:17 +02:00
parent 55be6437f1
commit 40d8090232
7 changed files with 35 additions and 17 deletions
+1 -3
View File
@@ -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");
+1 -3
View File
@@ -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
View File
@@ -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;
+5 -1
View File
@@ -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;
} }
+4 -1
View File
@@ -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}`);
+9
View File
@@ -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;
}
+12
View File
@@ -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", () => {