Skip to content

Commit

Permalink
Migrate away from ember-cli-head for <title> updates
Browse files Browse the repository at this point in the history
  • Loading branch information
raido committed Sep 3, 2020
1 parent d3a8a86 commit 0bb7d33
Show file tree
Hide file tree
Showing 13 changed files with 6,229 additions and 4,857 deletions.
24 changes: 9 additions & 15 deletions README.md
Expand Up @@ -8,17 +8,15 @@ This addon provides a helper for changing the title of the page you're on.
ember install ember-page-title
```

Add `{{head-layout}}` to your application's `application.hbs` template.

<details>
<summary>Fastboot vs Non-Fastboot Notes</summary>

### Compatibility

* Ember.js v3.12 or above
* Ember CLI v2.13 or above
* Node.js v10 or above

<details>
<summary>Fastboot vs Non-Fastboot Notes</summary>

#### Post Install Cleanup

As of v3.0.0 this addon maintains the page title by using the `<title>` tag in your document's `<head>`. This is necessary for [FastBoot](https://github.com/tildeio/ember-cli-fastboot) compatibility.
Expand Down Expand Up @@ -60,21 +58,17 @@ module.exports = function (environment) {
};
```

### Fastboot

When working with other addons that use `ember-cli-head`, you'll need to create a custom `head.hbs` file that exposes the `<title>` tag properly:

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

This file is added automatically if you use `ember install`. This is for all the folks using ember-cli-head addons like ember-cli-meta-tags.

### Deprecations

- Since **v5.2.2**: The `{{title}}` helper has been deprecated, use `{{page-title}}` instead, it has the same API. The
`{{title}}` helper was an AST transform and will be removed in the next major release.

### Upgrading notes for 5.x to 6.x

`ember-page-title` no longer requires the usage of `ember-cli-head`.

Please remove `{{head-layout}}` from your application's `application.hbs` route template.

### Upgrading notes for 3.x to 4.x

From 4.x onward, you need to have `{{head-layout}}` within your application's `application.hbs` template. Without this, you will not see a page title appear.
Expand Down
56 changes: 20 additions & 36 deletions addon/helpers/page-title.js
@@ -1,14 +1,7 @@
import { scheduleOnce } from '@ember/runloop';
import { inject as service } from '@ember/service';
import Helper from '@ember/component/helper';
import { set } from '@ember/object';
import { guidFor } from '@ember/object/internals';
import { assign } from '@ember/polyfills';
import { getOwner } from '@ember/application';

function updateTitle(tokens) {
set(this, 'title', tokens.toString());
}

/**
`{{page-title}}` is used to communicate with
Expand All @@ -17,13 +10,15 @@ function updateTitle(tokens) {
@method page-title
*/
export default Helper.extend({
pageTitleList: service(),
headData: service(),
tokens: service('page-title-list'),

get tokenId() {
return guidFor(this);
},

init() {
this._super();
let tokens = this.pageTitleList;
tokens.push({ id: guidFor(this) });
this._super(...arguments);
this.tokens.push({ id: this.tokenId });
},

compute(params, _hash) {
Expand All @@ -35,33 +30,22 @@ export default Helper.extend({
_hash._deprecate
);
}
let tokens = this.pageTitleList;
let hash = assign({}, _hash);
hash.id = guidFor(this);
hash.title = params.join('');
tokens.push(hash);
scheduleOnce('afterRender', this.headData, updateTitle, tokens);
let hash = assign(
{},
_hash,
{
id: this.tokenId,
title: params.join('')
}
);

this.tokens.push(hash);
this.tokens.scheduleTitleUpdate();
return '';
},

destroy() {
let tokens = this.pageTitleList;
let id = guidFor(this);
tokens.remove(id);

let router = getOwner(this).lookup('router:main');
let routes = router._routerMicrolib || router.router;
let { activeTransition } = routes || {};
let headData = this.headData;
if (activeTransition) {
activeTransition.promise.finally(function () {
if (headData.isDestroyed) {
return;
}
scheduleOnce('afterRender', headData, updateTitle, tokens);
});
} else {
scheduleOnce('afterRender', headData, updateTitle, tokens);
}
this.tokens.remove(this.tokenId);
this.tokens.scheduleTitleUpdate();
},
});
44 changes: 36 additions & 8 deletions addon/services/page-title-list.js
@@ -1,21 +1,25 @@
import { A } from '@ember/array';
import { getOwner } from '@ember/application';
import { inject as service } from '@ember/service';
import { scheduleOnce } from '@ember/runloop';
import Service from '@ember/service';
import { set, computed } from '@ember/object';
import { copy } from 'ember-copy';
import { capitalize } from '@ember/string';
import { isPresent } from '@ember/utils';

let isFastBoot = typeof FastBoot !== 'undefined';

/**
@class page-title-list
@extends Ember.Service
*/
export default Service.extend({
document: service('-document'),

init() {
this._super();
set(this, 'tokens', A());
set(this, 'length', 0);
this._removeExistingTitleTag();

let config = getOwner(this).resolveRegistration('config:environment');
Expand Down Expand Up @@ -112,7 +116,6 @@ export default Service.extend({
let tokens = copy(this.tokens);
tokens.push(token);
set(this, 'tokens', A(tokens));
set(this, 'length', this.length + 1);
},

remove(id) {
Expand All @@ -131,7 +134,6 @@ export default Service.extend({
let tokens = A(copy(this.tokens));
tokens.removeObject(token);
set(this, 'tokens', A(tokens));
set(this, 'length', this.length - 1);
},

visibleTokens: computed('tokens', {
Expand Down Expand Up @@ -190,6 +192,22 @@ export default Service.extend({
}
}),

scheduleTitleUpdate() {
let router = getOwner(this).lookup('router:main');
let routes = router._routerMicrolib || router.router;
let { activeTransition } = routes || {};
if (activeTransition) {
activeTransition.promise.finally(() => {
if (this.isDestroyed) {
return;
}
scheduleOnce('afterRender', this, this._updateTitle);
});
} else {
scheduleOnce('afterRender', this, this._updateTitle);
}
},

toString() {
let tokens = this.sortedTokens;
let title = [];
Expand All @@ -205,12 +223,26 @@ export default Service.extend({
return title.join('');
},

_updateTitle() {
const toBeTitle = this.toString();

if (isFastBoot) {
// in fastboot context "document" is instance of ember-fastboot/simple-dom document
let titleEl = this.document.createElement('title');
let titleContents = this.document.createTextNode(toBeTitle);
titleEl.appendChild(titleContents);
this.document.head.appendChild(titleEl);
} else {
this.document.title = toBeTitle;
}
},

/**
* Remove any existing title tags from the head.
* @private
*/
_removeExistingTitleTag() {
if (this._hasFastboot()) {
if (isFastBoot) {
return;
}

Expand All @@ -219,9 +251,5 @@ export default Service.extend({
let title = titles[i];
title.parentNode.removeChild(title);
}
},

_hasFastboot() {
return !!getOwner(this).lookup('service:fastboot');
}
});
6 changes: 0 additions & 6 deletions app/templates/head.hbs

This file was deleted.

0 comments on commit 0bb7d33

Please sign in to comment.