aurelia / router

A powerful client-side router.
MIT License
120 stars 115 forks source link

configureRouter method is not triggered, when the template is loaded dynamically(from server) #659

Open ayaanraj opened 4 years ago

ayaanraj commented 4 years ago

Hi all,

aurelia-framework - 1.3.0, aurelia-router - 1.7.1

home.js

import { inject, InlineViewStrategy } from "aurelia-framework";
import { HttpClient } from "aurelia-fetch-client";
import { PLATFORM } from "aurelia-framework";
PLATFORM.moduleName("child-router/child-router");
PLATFORM.moduleName("../welcome");
PLATFORM.moduleName("../users");

@inject(HttpClient)
export class Home {
  constructor(http) {
    this.http = http;
    this.viewTemplate = null;
  }

  activate() {
    this.loadView().then((res) => {
      this.viewTemplate = new InlineViewStrategy(res);
    });
  }

  loadView() {
    return this.http.fetch("api/home").then((response) => response.text());
  }
}

home.html

<template>
  <div if.bind="viewTemplate">
    <compose view.bind="viewTemplate"></compose>
  </div>
</template>

response from api/home

<template>
  <require from="child-router/child-router"></require>
  <child-router></child-router>
</template>

child-router/child-router.html

<template>
  <section class="au-animate">
    <h2>${heading}</h2>
    <div>
      <div class="col-md-2">
        <ul class="well nav nav-pills nav-stacked">
          <li
            repeat.for="row of router.navigation"
            class="${row.isActive ? 'active' : ''}"
          >
            <a href.bind="row.href">${row.title}</a>
          </li>
        </ul>
      </div>
      <div class="col-md-10" style="padding: 0;">
        <router-view></router-view>
      </div>
    </div>
  </section>
</template>

child-router/child-router.js

import { PLATFORM } from "aurelia-pal";

export class ChildRouter {
  heading = "Child Router";

  configureRouter(config, router) {
    alert("in route");
    config.map([
      {
        route: ["", "welcome"],
        name: "welcome",
        moduleId: PLATFORM.moduleName("../welcome"),
        nav: true,
        title: "Welcome",
      },
      {
        route: "users",
        name: "users",
        moduleId: PLATFORM.moduleName("../users"),
        nav: true,
        title: "Github Users",
      },
      {
        route: "child-router",
        name: "child-router",
        moduleId: PLATFORM.moduleName("../child-router"),
        nav: true,
        title: "Child Router",
      },
    ]);

    this.router = router;
  }

  bind() {
    alert("in the bind");
  }
}

As you can see above, I'm getting the template from the server and rendering it using InlineViewStrategy and in the server response, I have required a component(child-router) and using it.

Inside the required component(child-router), I have routes defined in it, I have absorbed that all the life cycle events are triggered, but the configureRouter method is not triggered, am I doing, anything wrong here.

please help me out.

bigopon commented 4 years ago

In the response from your api/home, you have

<template>
  <require from="child-router/child-router"></require>
  <child-router></child-router>
</template>

<child-router/> is loaded too late, because of if.bind="viewTemplate" I think, can you try remove that if?

ayaanraj commented 4 years ago

Hi @bigopon I have removed the if.bind="viewTemplate and tried it, but still configureRouter has not got triggered.

ayaanraj commented 4 years ago

Hi @bigopon any update on this issue.

bigopon commented 4 years ago

@ayaanraj I'm not sure if the usage you have there is supported, as normally, router view should be ready upfront.

cc @jwx @davismj @fkleuver

fkleuver commented 4 years ago

router-view is registered during compilation and so any kind of dynamic (via compose, etc) or conditional (with if.bind, etc) rendering of the router-view will lead to the registration happening too late. It must be statically present in the html template of the component you need configureRouter to be called on.

This is a design limitation in v1 and it will not be solved in v1, however it will work just fine in v2.