aurelia / router

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

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

Open RichTeaTime opened 7 years ago

RichTeaTime commented 7 years ago

I'm submitting a feature request

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.

balazsmeszegeto commented 7 years ago

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.

timfish commented 6 years ago

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;
  };
oneillci commented 6 years ago

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

TimVevida commented 5 years ago

@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 commented 5 years ago

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.

davismj commented 5 years ago

@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.