Routing to anchors on a form - ignoreUnknownRoutes

I know that this question has been asked before, but the only answer I could find is at
https://github.com/aurelia-contrib/aurelia-dynamic-html/issues/1 and
https://github.com/aurelia/router/pull/558
which refers to ignoreUnknownRoutes on the router.

Where is the ignoreUnknownRoutes on the router?

All I’m trying to do is (I thought this would be extremely trivial):

@autoinject
export class QuickLinksCustomElement {
  @bindable public legend: string;

  public list = [
    { id: "#purchases", text: "Purchases", active: "" },
    { id: "#production", text: "Production", active: "" },
    { id: "#profit-and-loss", text: "Profit and loss", active: "" },
    { id: "#cashflow", text: "Cashflow", active: "" },
    { id: "#kpis", text: "Key performance indices", active: "" },
    { id: "#variables", text: "Variables", active: "" }
  ];

  public clicked(index: number) {
    this.list.forEach(c => {
      c.active = "";
    });
    this.list[index].active = "active";
  }
}
<li repeat.for="item of list" class="nav-item">
   <a class="nav-link ${item.active}" href.bind="item.id" click.delegate="clicked($index)">${item.text}</a>
</li>
1 Like

ignoreUnknownRoutes was added and reverted shortly after, due to some unstable/non-well-specced behaviors related to pushState. I think you can work around using data-router-ignore/router-ignore attribute on anchors. Can you try that?

Sorry for delay in replying. I tried all variations, but still get

      <li repeat.for="item of list" class="nav-item">
        <a class="${item.active} btn btn-sm btn-primary mr-2" data-router-ignore href.bind="item.id" click.trigger="clicked($index) & debounce:20">${item.text}</a>
      </li>
aurelia-logging-console.js?dc89:45 ERROR [app-router] Error: Route not found: /kpis
    at AppRouter._createNavigationInstruction (aurelia-router.js?e32b:1097)
    at AppRouter.loadUrl (aurelia-router.js?e32b:1707)
    at BrowserHistory._loadUrl (aurelia-history-browser.js?d627:306)
    at BrowserHistory._checkUrl (aurelia-history-browser.js?d627:299)
error @ aurelia-logging-console.js?dc89:45
(anonymous) @ aurelia-logging.js?30fd:38
(anonymous) @ aurelia-router.js?e32b:1710
tryCatcher @ bluebird.js?f684:5276
Promise._settlePromiseFromHandler @ bluebird.js?f684:3297
Promise._settlePromise @ bluebird.js?f684:3354
Promise._settlePromise0 @ bluebird.js?f684:3399
Promise._settlePromises @ bluebird.js?f684:3475
(anonymous) @ bluebird.js?f684:175
(anonymous) @ bluebird.js?f684:4530
attributes (async)
(anonymous) @ bluebird.js?f684:4516
attributes (async)
scheduleToggle @ bluebird.js?f684:4524
schedule @ bluebird.js?f684:4533
Async.settlePromises @ bluebird.js?f684:174
Promise._reject @ bluebird.js?f684:3442
Promise._settlePromise @ bluebird.js?f684:3369
Promise._settlePromiseCtx @ bluebird.js?f684:3391
(anonymous) @ bluebird.js?f684:165
(anonymous) @ bluebird.js?f684:4530
attributes (async)
(anonymous) @ bluebird.js?f684:4516
attributes (async)
scheduleToggle @ bluebird.js?f684:4524
schedule @ bluebird.js?f684:4533
Async.invoke @ bluebird.js?f684:164
Promise._then @ bluebird.js?f684:3046
Promise.then @ bluebird.js?f684:2910
loadUrl @ aurelia-router.js?e32b:1707
_loadUrl @ aurelia-history-browser.js?d627:306
_checkUrl @ aurelia-history-browser.js?d627:299

How did you setup your top level router? You have to use config.options.pushState = true;, otherwise aurelia-router will work in hash mode. It means you cannot avoid aurelia-router with your hash href, even after a full page reload (router-ignore does that).

I hadn’t used config.options.pushstate = true.

I just tried, and its causing all kinds of weird problems…

  public configureRouter(config: RouterConfiguration, router: Router) {
    config.title = "Amberwood";
    // config.options.pushState = true;

    config.map([
      { route: ["", "home"], moduleId: PLATFORM.moduleName("modules/home/home"), name: "home", nav: true, title: "Home" },
      { route: "production/:id?", href: "production", moduleId: PLATFORM.moduleName("modules/production/production-edit"), name: "productionEdit", nav: true, title: "Production" },
      { route: "salesPrice", moduleId: PLATFORM.moduleName("modules/salesPrice/salesPrice-edit"), name: "salesPriceEdit", nav: true, title: "Sales Price" },
      { route: "costings/:id?", href: "costings", moduleId: PLATFORM.moduleName("modules/costings/costings-edit"), name: "costingsEdit", nav: true, title: "Costs" },
      { route: "warnings", moduleId: PLATFORM.moduleName("modules/company/companies-overview-list"), name: "companiesOverviewList", nav: true, title: "Warnings" },
      {
        route: "dictionaries", moduleId: PLATFORM.moduleName("modules/dictionaries/index"), nav: true, title: "Dictionaries", settings: {
          nav: [
            { href: "#/dictionaries/master", title: "Master Dictionary" },**
            { href: "#/dictionaries/companies", title: "Companies" }**
          ]
        }
      },
      { route: "dictionaries/master", moduleId: PLATFORM.moduleName("modules/dictionary/dictionary-edit"), name: "dictionaryEdit" },
      { route: "dictionaries/companies/:id?", moduleId: PLATFORM.moduleName("modules/company/company-edit"), name: "companyEdit" }
    ]);

    this.router = router;
  }
}

Note the

route: "dictionaries", moduleId: PLATFORM.moduleName("modules/dictionaries/index"), nav: true, title: "Dictionaries", settings: {
          nav: [
            { href: "#/dictionaries/master", title: "Master Dictionary" },**
            { href: "#/dictionaries/companies", title: "Companies" }**
          ]

I set config.option.pushstate=true and removed #/ from the href. The router picks up http://localhost/dictionaries/master but messes up the reference to the route to the server.

The route to the server is api/dictionary/MasterDictionary which works perfectly well without pushstate. It’s now been changed to https://localhost:5001/dictionaries/api/dictionary/MasterDictionary where it should be https://localhost:5001/api/dictionary/MasterDictionary

You need to use absolute path /api/dictionary/... when calling backend to avoid routing problem, because relative path api/dfd is related with current url path which could be / or /dictionary or /dictionary/master.

Also, aurelia-router doc recommended to use <base> tag in html head.
So here, you can add

<base href="/">

To index.html.

Plus aurelia router config to match it.

config.options.root = '/';

With base tag, all relative url request is related to the base href "/", not current browser url anymore. So it will work with your existing relative api call.

1 Like

Sorry for the delay in getting back to you.

I tried all your suggestions
config.options.pushstate = true;
config.options.root = "/"

_Layout.cshtml - <base href="/">

I changed all the relative references in app.ts configureRouter

Up to this point all the api calls are called correctly.

However , the anchor links are now all relative to the root giving me
ERROR [app-router] Error: Route not found: /cashflow.

I’ve tried adding data-router-ignore and router-ignore attributes to the link but it makes no difference.

Did you change those to-be-ignored #cashFlow to /cashFlow?

You cannot use /bla because router try to understand it.

Yes - I’ve tried just about all variations including add the page’s route where production is the name of the route in router.config.

      <li repeat.for="item of list" class="nav-item">
        <a class="btn btn-sm btn-outline-primary mr-2" data-router-ignore href.bind="'production/' + item.id">${item.text}</a>
      </li>

I’ve added in and taken out the /# from the links with all variations: just “#”, “/#”, “#/” and nothing changes.

I tried data-router-ignore router-ignore and nothing for the attribute

@autoinject
export class QuickLinksCustomElement {
  @bindable public legend: string;

  public list = [
    { id: "#purchases", text: "Purchases", active: "" },
    { id: "#production", text: "Production", active: "" },
    { id: "#profit-and-loss", text: "Profit and loss", active: "" },
    { id: "#cashflow", text: "Cashflow", active: "" },
    { id: "#kpis", text: "Key performance indices", active: "" },
    { id: "#variables", text: "Variables", active: "" }
  ];

  public clicked(index: number) {
    this.list.forEach((c, idx) => {
      c.active = "";
    });
    this.list[index].active = "active";
  }
}

The status bar looks like
http://localhost:5000/production#cashflow
but it still gets routed to the router and not to the anchor.

I just tried myself, could not get it to work :frowning:
Looks like aurelia router still want to understand product#cashflow as a whole piece for routing, instead of just use product then let browser jump to #cashflow.

1 Like

Aurelia official doc site uses hash to locate doc, I need to dig into that to see how it works.

Like this one, you click navigation at left side, it jumps to different section of the current page.

https://aurelia.io/docs/cli/cli-bundler/basics

LOL, Aurelia site-generator is NOT using aurelia-router, it got a manual router implementation.

@EisenbergEffect is that because that aurelia-router doesn’t play well with hash link? It feels like a missing feature from aurelia-router.

1 Like

There was a PR to enable this feature. Unfortunately we had to revert it due to non-well-spec’d behavior for push state users.

1 Like

The routing needs of the site are not that complex. I didn’t feel a need to require router, route-recognizer and templating-router for what was a relatively simple navigation scheme that could be built without much trouble on top of the history-browser module directly. One of the reasons I like having the history-browser module separate from the router is to enable the authoring of custom routers for simple scenarios, without having to worry about the ugliness of the underlying history APIs. My choice in this case had nothing to do with any features that the router itself did or did not support.

I’ve reverted to options.pushState = false.

I guess I can live with the Route not found error.

Still - I would have thought that this is a fairly basic requirement for the router to allow you to navigate to anchors on the same page.

Thanks for the help anyway
Jeremy