router icon indicating copy to clipboard operation
router copied to clipboard

Please expose the title generated by NavigationInstruction._buildTitle, or make the method public.

Open RichTeaTime opened this issue 8 years ago • 6 comments

I'm submitting a feature request

  • Library Version: 1.1.1

  • Browser: all

  • Language: all | TypeScript 2.0.3

Current behavior: When the page title is updated via setTitle or updateTitle, the result of the _buildTitle call is sent directly to the router.history object. Aside from querying and parsing document.title from the browser, there is no way for an aurelia component to retrieve the generated value. Prior to 1.1.1, we could just query config.navModel.title from the NavigationInstruction, but now the call to router.transformTitle could result in a different value.

Expected/desired behavior: When _buildTitle is called on NavigationInstruction, set a .title property on the NavigationInstruction. This could be Example | Example | Page for the top-level instruction (with no parentInstruction), then Example | Page, then Page for the child instructions within it (i.e. just set it from the recursive _buildTitle method).

This would make it easy to implement navigation hooks, allowing implementation of breadcrumbs, history, undo/redo, etc... using the title of a page at the time that it was generated.

This would also avoid a current limitation of the NavigationInstruction: because the title is generated from config.navModel.title, subsequent calls to setTitle from other instances of the same page will change ALL titles on ALL NavigationInstructions derived from it. Implementing this approach would mean that a NavigationInstruction.title value would only be refreshed if updateTitle was triggered on it.

OTHERWISE, can NavigationInstruction._buildTitle be made public? (e.g. expose as NavigationInstruction.buildTitle()). This would provide a simple interface for retrieving the current title value when router:navigation:complete event fires.

  • What is the motivation / use case for changing the behavior? I'm writing a breadcrumb component, and currently either need to hack (NavigationInstruction.prototype['_buildTitle'].call(...)) or generate the title from the NavModel, and - with transformTitle - that's not DRY.

RichTeaTime avatar Feb 13 '17 13:02 RichTeaTime

I'd go a bit further and make the title generation costumizable/overwritable. What if we'd use a different format, eg. Root / Child / ChildOfChild? Currently, we could do that by adding a pipeline setup at "postRender" and re-generate the title and re-publish the new.

balazsmeszegeto avatar Mar 23 '17 10:03 balazsmeszegeto

In Electron, the page title can automatically be used for the window title and the current ordering makes less sense in this case. I'm guessing the existing order favours the narrow width of browser tabs?

Current title:

Graph - Live Data - Our App

Required title:

Our App - Live Data - Graph

Are there any preferences on how custom title generation should be implemented? I would consider doing a PR.

Edit

I achieved this by overriding _buildTitle with the following:

  (NavigationInstruction.prototype as any)._buildTitle = function() {
    const separator = ' - ';

    let title = '';
    const childTitles = [];

    // tslint:disable-next-line:forin
    for (const viewPortName in this.viewPortInstructions) {
      const viewPortInstruction = this.viewPortInstructions[viewPortName];

      if (viewPortInstruction.childNavigationInstruction) {
        const childTitle = viewPortInstruction.childNavigationInstruction._buildTitle(
          separator
        );
        if (childTitle) {
          childTitles.push(childTitle);
        }
      }
    }

    if (this.router.title) {
      title +=
        (title ? separator : '') +
        this.router.transformTitle(this.router.title);
    }

    if (this.config.navModel.title) {
      title +=
        (title ? separator : '') +
        this.router.transformTitle(this.config.navModel.title);
    }

    if (childTitles.length) {
      title += (title ? separator : '') + childTitles.reverse().join(separator);
    }

    return title;
  };

timfish avatar May 20 '18 11:05 timfish

I agree with having this as a configurable option. The current implementation of _buildTitle is very opinionated as to what the document title should be.

I have a requirement that our document.title always just display as {App Name} and not update with any route change, and I'd rather not do this by overriding the NavigationInstruction._buildTitle function as this would not seem to be best practise. This is my only option AFAIK at the moment

oneillci avatar May 21 '18 04:05 oneillci

@oneillci Your use case is easily solved by just setting the title for the main router and not setting any sub route titles. Aurelia should then only show the main router title, no separators, no subroutes.

TimVevida avatar Sep 03 '19 15:09 TimVevida

I am interested in a method to transform the title with extra information about the current route and its params. I want to conditionally show the title of a parent route based on if it is the currently active route or not. This is not possible at the moment, so I walk over the NavigationInstructions on router:navigation:success an roll my own title. It would be nice if Aurelia could facilitate in such more complex use cases.

TimVevida avatar Sep 03 '19 15:09 TimVevida

@TimVevida I agree. Can you please propose (a) a new API that would achieve what you're looking for and (b) a demonstration of how the new API would not break any of the existing behavior around _buildTitle.

davismj avatar Sep 21 '19 19:09 davismj