Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(platform browser): introduce Meta service #12322

Merged
merged 1 commit into from
Dec 9, 2016

Conversation

DzmitryShylovich
Copy link
Contributor

Fixes #11115

@DzmitryShylovich DzmitryShylovich force-pushed the feature/11115 branch 14 times, most recently from 16bdc30 to 8d0706f Compare October 15, 2016 12:14
@DzmitryShylovich DzmitryShylovich changed the title [WIP] feat(platform browser): introduce Meta service feat(platform browser): introduce Meta service Oct 15, 2016
@DzmitryShylovich
Copy link
Contributor Author

CI fails with

+/tmp/angular-build/typings-test.1476534211/node_modules/.bin/tsc -p tsconfig.json
node_modules/@angular/platform-browser/src/browser/meta.d.ts(13,46): error TS1110: Type expected.
node_modules/@angular/platform-browser/src/browser/meta.d.ts(26,44): error TS1110: Type expected.

I don't know what I'm missing.

@vicb vicb added action: review The PR is still awaiting reviews from at least one requested reviewer area: core Issues related to the framework runtime labels Oct 15, 2016
Copy link
Contributor

@jeffbcross jeffbcross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General question, is there any benefit to setting meta tags in the browser (instead of just pre-render)? Like do Chrome extensions like Pocket look at the current meta tags of content?

* @param contentValue new content value
* @returns {void}
*/
setContent(metaName: string, contentValue: string): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reasoning for not implicitly creating the tag if it doesn't exist? For example, for something like open graph tags, the existence of certain types of tags depends on the page's content. I.e. the og:video tag should not be present if there's no video.

Copy link
Contributor

@FrozenPandaz FrozenPandaz Oct 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some meta tags have a "property" and no "name" such as Facebook:

Facebook Open Graph

I know this is not web standard but is this something that should be implemented in like a PropertyMetaTag or something?

W3 Meta Tag

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Almost any respectable application will use property tags as well, even if they are not standard.
If this doesn't get implemented natively, then we'll have to do our own service anyway, which is just duplicating code/effort.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FrozenPandaz I think you're agreeing with my original comment? My comment was positing that the existence of some tags, such as open graph tags, depends on content, so the meta service should manage creating/removing tags instead of just updating attributes of existing tags.

One of my other review comments addresses changing the API to support arbitrary attribute names.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just commenting on the same code..

What I meant is that Metas should not only have a name property but also a... property property.

I do agree with your comment though. There is no one set of metadata for every single app. I believe we should start with a blank slate and have the developer set them 1 by 1.

It should create it if its not there already, edit it if it is there, and it should have the ability to remove it.. I wonder how that will work with SPAs.. we might want to have a removeAll method as well.

* @param metaName meta tag name
* @returns {HTMLElement|null}
*/
getMeta(metaName: string): HTMLElement|null { return getDOM().query(`meta[name=${metaName}]`); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather the get/set methods be more generic than include the getMeta method and return the element. setContent could accept an optional third argument attributeName='content'.

Or is there another reason to have the getMeta method other than setting arbitrary attributes?

getContent(metaName: string): string|null {
const meta: HTMLElement = this.getMeta(metaName);
return meta ? meta.getAttribute(CONTENT_ATTR) : null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A remove method seems appropriate since this service is a map-like interface, as long as the setContent method would implicitly create elements.

@jeffbcross jeffbcross self-assigned this Oct 24, 2016
@jeffbcross
Copy link
Contributor

By the way the TS failures are because of returning union types, which is not compatible with TS 1.8.

@lacolaco
Copy link
Contributor

lacolaco commented Oct 25, 2016

@jeffbcross It's needed to change metadata for sharing content after each routing navigation. This is for second+ views.

expect(actual).toEqual(META_CONTENT);
});

it('should return meta element', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeated description

@zoechi
Copy link
Contributor

zoechi commented Oct 30, 2016

Does this work with server-side rendering and Web Worker when it reads from the DOM?

@jeffbcross
Copy link
Contributor

jeffbcross commented Oct 31, 2016

@laco0416 thanks, I'm looking for documentation about common extensions like pocket to verify that they actually read the meta tags inside the browser, rather than re-requesting the content. Can you provide any links to confirm that popular extensions actually look at the browser state?

@jeffbcross
Copy link
Contributor

@DzmitryShylovich do you plan to update this PR with requested changes?

@DzmitryShylovich
Copy link
Contributor Author

ie doesn't support remove https://travis-ci.org/angular/angular/jobs/181829865 :)

@vicb
Copy link
Contributor

vicb commented Dec 7, 2016

BrowserDomAdapter.remove() uses removeChild

getDOM().getElementsByTagName(doc, 'head')[0].appendChild(defaultMeta);
});

afterEach(() => defaultMeta.remove());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getDom().remove(defaultMeta);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... or use your own service :)

@DzmitryShylovich
Copy link
Contributor Author

@vicb so what about dom adapter injection? I don't fully understand your point.

@vicb
Copy link
Contributor

vicb commented Dec 8, 2016

// ...
{provide: Meta, useFactory: getMeta}
// ...

function getMeta(): Meta {
  return new Meta(getDom());
}

@DzmitryShylovich
Copy link
Contributor Author

DzmitryShylovich commented Dec 8, 2016

updated (seems circleci is dead)

@vicb vicb added action: merge The PR is ready for merge by the caretaker and removed action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews labels Dec 9, 2016
@vicb
Copy link
Contributor

vicb commented Dec 9, 2016

Thanks !

@vicb vicb merged commit 72361fb into angular:master Dec 9, 2016
@DzmitryShylovich DzmitryShylovich deleted the feature/11115 branch December 9, 2016 07:24
@MarkPieszak
Copy link
Member

Do we know if this is slated for 2.4? @vicb

@jeffbcross
Copy link
Contributor

@MarkPieszak I believe there is no 2.4 release planned (see 2.3 blog post) so this would be in the first beta for 4.0 (See @IgorMinar's talk on the subject).

@MarkPieszak
Copy link
Member

Family over past few days, I saw something about that, but thought it was an April Fools joke (in December) haha.

So March then, great! I was just wondering since this makes life easier for Universal users, think we talked about that the other week.

@jeffbcross
Copy link
Contributor

@MarkPieszak yep, a big motivator of this API was for pre-rendering. Final will be in March, but betas will start being released soon :).

@MarkPieszak
Copy link
Member

@jeffbcross great! Messaged you on the slack, not sure if you still use that one

@kodeine
Copy link

kodeine commented Jan 25, 2017

@DzmitryShylovich is there any docs on how to use this? Also which version of angular this is supported?

@DzmitryShylovich
Copy link
Contributor Author

@kodeine

is there any docs on how to use this?

not yet. you can find usage examples in the tests

which version of angular this is supported?

beta 4.0

@goelinsights
Copy link

goelinsights commented Apr 7, 2017

@DzmitryShylovich @jeffbcross was looking at the new API for meta -- is it possible to use it for link rel= tags as well?

Or should we stick with the old pattern along the lines below. If the second, do you know what where the old getDOM moved to?...this import broke for me

import { getDOM } from '@angular/platform-browser/src/dom/dom_adapter';

// ...
this.DOM = getDOM();

private getOrCreateLinkElement(name: string): HTMLElement {
  let el: HTMLElement;
  el = this.DOM.query('link[rel=' + name + ']');
  if (el === null) {
    el = this.DOM.createElement('link');
    el.setAttribute('rel', name);
    this.headElement.appendChild(el);
  }
  return el;
}

@MarkPieszak
Copy link
Member

Check out here for a temporary solution until a DocumentService is implemented within Core
#15776 (comment)

@fulls1z3
Copy link

@MarkPieszak I checked the linkService and it seems awesome.

Actualy I am planning to use such a similar htmlService to set the lang attribute of html tag (to the working language) as well as canonical links, right at the meta utility (@nglibs/meta) generating the meta tags based on route definitions.

Meanwhile, many thanks to @DzmitryShylovich for Meta/Title services. This way, the meta utility avoids direct manipulation of DOM and just depends on DomAdapter (in Angular 2) or on Meta/Title services (in Angular 4) - and works well with server-side rendering as well as client-side rendering.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: core Issues related to the framework runtime cla: yes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implementing a Meta class for getting and changing HTML meta tags