GithubHelp home page GithubHelp logo

kimroen / ember-cli-document-title Goto Github PK

View Code? Open in Web Editor NEW
217.0 8.0 61.0 676 KB

Adding document title behaviour to your ember app

License: MIT License

JavaScript 85.59% HTML 13.56% Handlebars 0.85%
ember javascript ember-addon

ember-cli-document-title's Introduction

Sane Document Title Build Status Ember Observer Score Code Climate

This addon adds sane document.title integration to your ember app.

Originally based on this gist by @machty, and since improved upon by many fabulous contributors.

Tested to work with Ember 1.13.13 and up.

Install

Install by running

ember install ember-cli-document-title

So, how does this work?

This adds two new keys to your routes:

  1. titleToken
  2. title

They can be either strings or functions.

Every time you transition to a route, the following will happen:

  1. Ember will collect the titleTokens from your leafmost route and bubble them up until it hits a route that has title defined. titleToken is the name of the route's model by default.
  2. If title is a string, that will be used as the document title
  3. If title is a function, the collected titleTokens will be passed to it in an array.
  4. What is returned from the title function is used as the document title.

Examples!

Simple, static titles

If you just put strings as the title for all your routes, that will be used as the title for it.

// routes/posts.js
export default Ember.Route.extend({
  title: 'Our Favorite posts!'
});

// routes/post.js
export default Ember.Route.extend({
  title: 'Please enjoy this post'
});

Dynamic segments with a static part

Let's say you want something like "Posts - My Blog", with "- My Blog" being static, and "Posts" being something you define on each route.

// routes/posts.js
export default Ember.Route.extend({
  titleToken: 'Posts'
});

This will be collected and bubble up until it hits the Application Route

// routes/application.js
export default Ember.Route.extend({
  title: function(tokens) {
    return tokens.join(' - ') + ' - My Blog';
  }
});

Dynamic title based on model info

In this example, we want something like "Name of current post - Posts - My Blog".

Let's say we have this object as our post-model:

Ember.Object.create({
  name: 'Ember is Omakase'
});

And we want to use the name of each post in the title.

// routes/post.js
export default Ember.Route.extend({
  titleToken: function(model) {
    return model.get('name');
  }
});

This will then bubble up until it reaches our Posts Route:

// routes/posts.js
export default Ember.Route.extend({
  titleToken: 'Posts'
});

And continue to the Application Route:

// routes/application.js
export default Ember.Route.extend({
  title: function(tokens) {
   tokens = Ember.makeArray(tokens);
   tokens.unshift('My Blog');
   return tokens.reverse().join(' - ');
  }
});

This will result in these titles:

  • On /posts - "Posts - My Blog"
  • On /posts/1 - "Ember is Omakase - Posts - My Blog"

Async titles using promises

You may be in a situation where it makes sense to have one or more of your titleTokens be asynchronous. For example if a related model is async, or you just enjoy working with Promises in your past-time.

Luckily, you can return a promise from any of your titleToken functions, and they will all be resolved by the time your title function receives them.

An example! Let's say we have these two Ember Data models; a post and its user:

// models/post.js
export default DS.Model.extend({
  name: DS.attr('string'),
  author: DS.belongsTo('user', { async: true })
});
// models/user.js
export default DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string')
});

In our document title, we want the name of the author in parenthesis along with the post title.

The author relationship is async, so getting it will return a promise. Here's an example where we return a promise that resolves to the post name plus the author name in parenthesis:

// routes/post.js
export default Ember.Route.extend({
  titleToken: function(model) {
    var postName = model.get('name');

    return model.get('author')
      .then(function (user) {
        var authorName = user.get('firstName') + user.get('lastName');

        return postName + '(by ' + authorName + ')';
      });
  }
});

With the same configuration for Posts and Application routes as in the previous example, this will result in this title:

  • On /posts/1 - "Ember is Omakase (by John Smith) - Posts - My Blog"

It's worth noting that the page title will not update until all the promises have resolved.

Use with ember-cli-head

Using ember-cli-document-title with ember-cli-head is very straight forward and allows you to use the wonderful route based declarative API for title and still easily add other things to the document's <head> (i.e. meta tags).

Only a few tweaks are needed to use both of these addons together:

  • Install both addons:
ember install ember-cli-head
ember install ember-cli-document-title
  • Add headData and setTitle to your app/router.js:
const Router = Ember.Router.extend({
  location: config.locationType,
  headData: Ember.inject.service(),

  setTitle(title) {
    this.get('headData').set('title', title);
  }
});
  • Remove <title> from your app/index.html.

  • Update app/templates/head.hbs (added by ember-cli-head):

{{! app/templates/head.hbs }}

<title>{{model.title}}</title>

ember-cli-document-title's People

Contributors

artsyca avatar blimmer avatar dependabot[bot] avatar dhaulagiri avatar elwayman02 avatar gpoitch avatar kimroen avatar kratiahuja avatar mnutt avatar poohitan avatar pwfisher avatar raido avatar rwjblue avatar scalvert avatar sinled avatar sly7-7 avatar snewcomer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ember-cli-document-title's Issues

Fastboot Support

This add-on is mentioned to support Ember Fastboot apps but I'm unable to see it actually work as expected. It does work normally when EmberJS is loaded, but when viewing the site source contents, the title is the same as written in "app/index.html" file. As a Ember Fastboot app I would expect for the title tag to change based on the configuration set. If this is a Fastboot issue, please disregard my issue. Thanks!

Set up tests for fastboot

In order to make sure that ember-cli-document-title keeps working as intended with and without fastboot and before and after Glimmer 2, we need to add some tests for running it inside fastboot.

Some resources:

In fastboot, we just need to test the first render of everything, so we don't need as many tests as the normally running app does, luckily.

Support for other meta tags

This is a great little nifty library! I'm currently using it on https://www.ludu.co together with Prerender.io in order not to screw up SEO with Ember. :)
Do you have any plans on extending it to support for example description tags or Facebook's open graph tags? In my case, I would love to be able to set the og:image based on the model's image for example.

Get to route params

Like this:

titleToken: function(model, params) {
    return params.status_id;
}

Major: Intent to deprecate in favor of ember-page-title

This issue proposes sunsetting this addon in favor of ember-page-title. The last workable release would be 1.1.0. Minor bump and updates to README will follow similar behaviour to ember-i18n

There are a number of reasons to consider this.

Benefits

  1. Rally around a single blessed solution for the community. Both of these addons accomplish approximately the same behaviour with little differentiation in end result. This will reduce fragmentation for users just starting out with Ember as well.
  2. Will not work with 4.0. See coming Ember global deprecation found in the code here.
  3. API, although at the time was a great solution, now can be accomplished through the public router service APIs.

Downsides

  1. Significant refactor for those users that need to adopt a new solution.

Please let me know in this issue if you have any thoughts or concerns!

close #81 #104

Fix automatic test runs

The tests running on travis seems to have stopped working. Maybe something needs to be updated.

TypeScript ambient type information

Posting here for others to use.

Create a file in your project with the following contents

app/ember-cli-document-title.d.ts
declare module 'ember' {
  namespace Ember {
    interface Route {
      title: string;
    }
  }
}

No such file or directory with lazy ember-engine

I'm seeing the following error with a lazy in-repo-engine:

Error: ENOENT: no such file or directory, open '/someproject/tmp/source_map_concat-input_base_path-OKV17DZi.tmp/vendor/document-title/document-title.js'

The in-repo-engine has the ember-cli-document-title listed in the package.json dependency field.

Consider moving this repository to its own org

There are a number of open issues and PRs on this repo, and I believe there's desire for the community to help maintain it. May I propose we move this repo to its own org, and add some Admins to it to help drive it forward?

A common practice would be to create an org of the same name, and move it under.

ember-cli-document-title/ember-cli-document-title

DEPRECATION: An addon is trying to access project.nodeModulesPath.

The following deprecation is thrown on a new Ember 2.18.0 Version when starting the server. It seems some package needs to be updated.

This is not a reliable way to discover npm modules. Instead, consider doing: require("resolve").sync(something, { basedir: project.root }). Accessed from: new NPMDependencyVersionChecker (/Users/username/emberApp/node_modules/ember-cli-document-title/node_modules/ember-cli-version-checker/src/npm-dependency-version-checker.js:11:33)

Installing causes certain Sinon tests to fail

Repro:

  1. Create a test with a sinon.rejects() stub in it. Check that it passes.
  2. Install ember-cli-document-title
  3. Rerun test, it will now fail with an unexpected error.

I have broken down what in the addon causes the error and traced it to this line:
var Promise = Ember.RSVP.Promise;
In vendor/document-title/document-title.js.

I believe the problem is similar to what is described here:

emberjs/ember-qunit#300

Has anyone experienced this before? Or implemented any fixes? I'd imagine that the simplest fix is just to either remove the line completely and use native promises in the addon or change the name of the variable into which Ember.RSVP is imported.

Also pass tokens to setTitle

Hello,

It could be quite useful to have access to the whole list of token in the router's setTitle method in order to make them accessible to a template, in order to output a structured breadcrumb.

      // Stubbable fn that sets document.title
-      this.router.setTitle(finalTitle);
+      this.router.setTitle(finalTitle, tokens);

Support changing title outside of route transitions

Firstly, Thanks for the great plugin. I'm using this plugin to show a list, where I want to show the list count in the title. So, I tried .property() on titleToken function but It didn't work. I think we should add support for this functionality for dynamic title update.

Failing on 2.18

With 2.17.2 and earlier, everything worked without issue.

Upon upgrading to 2.18.0, the title method never gets invoked.

Deprecation warning starting with Ember 3.1

After updating to Ember 3.1 I've seen the following deprecation warning in our test suite logs:

DEPRECATION: Route#router is an intimate API that has been renamed to Route#_router. However you might want to consider using the router service [deprecation id: ember-routing.route-router] See https://emberjs.com/deprecations/v3.x#toc_ember-routing-route-router for more details.

It appears to be related to the use of self.router at

self.router.setTitle(finalTitle);

Title token using an async relationship

Hi there! First off, thanks a lot for this great add-on. I've been using it for a while and just found out a (minor) issue.

I have a models/foo.js with an async relationship to a user such as:

export default DS.Model.extend({
  title: DS.attr('string'),
  user: DS.belongsTo('user', { async: true })
});

In my routes/foo.js I have the following titleToken:

export default Ember.Route.extend({
  titleToken(model) {
    return model.get('user.firstName');
  }
});

Because useris async, user.firstNameis undefined at this point (user is still a Promise). When the promise is resolved, the title does not recompute so my title stays empty.

Would you have any recommendation about how to circumvent this issue? Thanks!

Incompatible with Ember 3.7?

Seems that the recent changes around the router service in Ember 3.7 breaks the add-on.

After upgrading I started to get this error:

Build Error (prember)

Cannot read property 'setTitle' of undefined

After digging through my node modules for setTitle, the only hit was this add-on.

Support for Auto Page Title with I18n

Thanks for this project, it's awesome to not have to have @machty 's source just copy/pasted into our project anymore.

We originally modified the gist just slightly to allow automatically providing a page title in our Ember I18n translation file so we didn't need to create a route file simply to provide a title or titleToken.

To get it working with this add-on we made use of an initializer to support the auto-lookup. Something like this:

import Ember from 'ember';

export function initialize(/* container, application */) {
  Ember.Route.reopen({
    titleToken: Ember.computed('routeName', function() {
      var pageTitleKey = `pageTitles.${this.get(routeName)}`;
      if(Ember.I18n.exists(pageTitleKey)) {
        return Ember.I18n.t(pageTitleKey);
      }
    })
  });
}

export default {
  name: 'route',
  initialize: initialize
};

and then we provide a translation for the route name in our translations file, like this:

en = {
  pageTitles: {
    application: 'My Page Name'
    ...
  }
}

I'm happy to keep-on-keepin' on with our custom re-open but I was curious if this sort of thing would be helpful for anyone else using this project.

Update for modern Ember

The current implementation has worked well for a long time, but:

  • it won't work with Ember 4, since the Ember global has been deprecated
  • I think everything this needs to do in terms of lifecycle behavior (and probably quite a bit of the rest of it) can actually be done with public API now, via the router service events
  • There's a fair bit of code in here that exists only to support Ember <2.0.0, which can also be safely dropped

An alternative approach might be: deprecate this in favor of the framework-supplied ember-page-title addon, which supports much of the same behavior.

Please release new version with Babel 6

I notice that you have ember-cli-babel listed as version 6.x in master but not in the latest release. Could you please release a version with babel 6?

Thanks!

Crash with Glimmer2 / Ember 2.9.0-alpha

Here is the stack:

on-error.js:77 Error: Property set failed: object in path "_dom.document" could not be found or was destroyed.
    at setPath (ember.debug.js:19288)
    at Object.set (ember.debug.js:19208)
    at Class.setTitle (document-title.js:85)
    at Class.collectTitleTokens (document-title.js:65)
    at Object.triggerEvent (ember.debug.js:26166)
    at Object.trigger (ember.debug.js:53740)
    at Object.trigger (ember.debug.js:52451)
    at Class.send (ember.debug.js:25514)
    at Class.updateTitle (document-title.js:77)
    at Object.applyStr (ember.debug.js:20768)

I believe the problem is that container.lookup('renderer:-dom') has changed it's structure and no longer has _dom on it. See:

With Ember 2.7:
screen shot 2016-08-21 at 9 22 39 pm

With Ember 2.9.0-alpha:
screen shot 2016-08-21 at 9 23 16 pm

I'll see if I can figure out a solution and submit a PR.

Ember-CLI 0.1.5 Does not seem to apply this addon

Hello, I just created a new project with 0.1.5 installed this addon, the same way i installed in an older project, but the addon does not seem to apply itself correctly? none of the titles or title tokens get written to doc title. I'm not sure what changed? Maybe the addon package itself? or perhaps the routes and router changed somehow?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.