Meta tags

132 views
Skip to first unread message

Joberto Diniz

unread,
Oct 3, 2014, 11:12:52 AM10/3/14
to ang...@googlegroups.com
I have the following in <head> of html:

<meta name="{{meta.name}}" property="{{meta.property}}" content="{{meta.content}}" ng-repeat="meta in metas" />

metas is an array that is added to $rootScope. However, there are meta tags which require name and other which require property, but not both. So, the way it is implemented, some name ou property will be empty, and that is a problem.

I thought of creating a directive <meta-tags> but it seems angular doesn't parse it in <head> section. Any ideas?

Majid Burney

unread,
Oct 3, 2014, 1:51:57 PM10/3/14
to ang...@googlegroups.com
Angular will definitely apply directives in <head>, unless you’re bootstrapping the application (with ng-app) somewhere other than <html>, such as <body>.

But if Angular is able to interpolate expressions and ng-repeat, then it should be able to use your custom directive. Something is likely off in the directive definition.

Joberto Diniz

unread,
Oct 3, 2014, 2:01:59 PM10/3/14
to ang...@googlegroups.com
Instead of evaluate the directive in the HEAD, angular is evaluating in the BODY, but the <meta name="{{meta.name}}" property="{{meta.property}}" content="{{meta.content}}" ng-repeat="meta in metas" /> is being evaluating in the HEAD. Weird.

I bootstrap angular manually, as I need to get some config values from server before angular kicks in.

Christopher O'Donnell

unread,
Oct 3, 2014, 2:18:34 PM10/3/14
to ang...@googlegroups.com
Hey, I've actually wrote a service for this. It's very new, I wrote it for a project I am working on now, and wrote it quickly so it could definitely use improvements. I may just create a gist or something if people want to contribute.


It solves your issues regarding using the proper name attributes, etc. 

- Chris

Joberto Diniz

unread,
Oct 3, 2014, 2:30:46 PM10/3/14
to ang...@googlegroups.com
"It solves your issues regarding using the proper name attributes, etc. "

Well, I don't see it.
My issue is that sometimes I need to set "name" and not "property" and sometimes I need to set "property" and not "name". I don't see your code fixing that.

Majid Burney

unread,
Oct 3, 2014, 2:41:10 PM10/3/14
to ang...@googlegroups.com
What does your manual bootstrap code look like?

Joberto Diniz

unread,
Oct 3, 2014, 2:44:17 PM10/3/14
to ang...@googlegroups.com
Essencially:

angular.bootstrap(document.documentElement, ['itaas.main']);



One could ask why "document.documentElement"? The answer: https://groups.google.com/d/msg/angular/LAk9oZqRx24/mPXPj495WlEJ

Majid Burney

unread,
Oct 3, 2014, 3:02:32 PM10/3/14
to ang...@googlegroups.com
Interesting, it seems the issue is in using the element directive syntax in <head>. Plunk: http://plnkr.co/edit/DTbGsyp7CnpO5M7mYXkb?p=preview

Swap the element usage of that test directive for the attribute usage and you’ll see that the content stays in <head> where it belongs.

This seems to be browser behavior and nothing to do with Angular: if the browser sees illegal elements in <head>, it just moves them to <body> where it expects you meant to put them. I’m sure it’s all in the html spec but I’m not going to look for it, that sounds boring.

Joberto Diniz

unread,
Oct 3, 2014, 3:14:21 PM10/3/14
to ang...@googlegroups.com
Thanks. That will help!
Message has been deleted

Christopher O'Donnell

unread,
Oct 3, 2014, 3:43:24 PM10/3/14
to ang...@googlegroups.com
you're right, i had solved the issue only for the 'http-equiv' vs 'name'=20
tags. Did not take property into account. It's been updated:

http://pastebin.com/hBp7yxGJ (line 111)

So basically anywhere in your app you can run something like this:

MetaService.set([
 
{title: 'Heres a title'},
 
{name: 'description', content: 'Description'},
 
{canonical: 'http://....'},
 
{rel: 'image_src', href: '/path/to/image'},
 
{property: 'og:title', content: 'title'},
 
{property: 'og:description', content: 'Description'},
 
{property: 'og:image', content: '/path/to/image'},
 
{property: 'og:url', content: url}
]);

and in your head:
<meta ng-attr-name=3D"{{ meta.name }}" ng-attr-property=3D"{{ meta.property= }}"=20 ng-attr-http-equiv=3D"{{ meta['http-equiv'] }}" ng-attr-content=3D"{{=20 meta.content }}" ng-attr-charset=3D"{{ meta.charset }}" ng-attr-data-ng-rep= eat =3D"meta in metas">

Joberto Diniz

unread,
Oct 3, 2014, 3:50:54 PM10/3/14
to ang...@googlegroups.com
I still don't see it.
If meta.name is empty, the following code:

<meta ng-attr-name="{{ meta.name }}" ng-attr-property="{{ meta.property }}" ng-attr-http-equiv="{{ meta['http-equiv'] }}" ng-attr-content="{{ meta.content }}" ng-attr-charset="{{ meta.charset }}" ng-attr-data-ng-repeat="meta in metas">

will output <meta name=""
that is, an empty value for name, won't it?

Christopher O'Donnell

unread,
Oct 3, 2014, 4:33:55 PM10/3/14
to ang...@googlegroups.com
According to Angular it's not supposed to:

https://docs.angularjs.org/guide/directive

We would expect Angular to be able to bind to this, but when we check the console we see something likeError: Invalid value for attribute cx="{{cx}}". Because of the SVG DOM API's restrictions, you cannot simply writecx="{{cx}}".

With ng-attr-cx you can work around this problem.

If an attribute with a binding is prefixed with the ngAttr prefix (denormalized as ng-attr-) then during the binding it will be applied to the corresponding unprefixed attribute. This allows you to bind to attributes that would otherwise be eagerly processed by browsers (e.g. an SVG element's circle[cx] attributes). When using ngAttr, the allOrNothing flag of $interpolate is used, so if any expression in the interpolated string results in undefined, the attribute is removed and not added to the element.


For example, we could fix the example above by instead writing:

<svg>
<circle ng-attr-cx="{{cx}}"></circle>
</svg>

That being said it looks like it still is appending that attribute in my code. 

<meta ng-attr-name="{{ meta.name }}" ng-attr-property="{{ meta.property }}" ng-attr-http-equiv="{{ meta['http-equiv'] }}" ng-attr-content="{{ meta.content }}" ng-attr-charset="{{ meta.charset }}" ng-attr-data-ng-repeat="meta in metas" class="ng-scope" name="" property="og:description" http-equiv="" content="Bacon ipsum dolor sit amet leberkas fatback spare ribs, bresaola ribeye ground round beef ribs. Pig frankfurter porchetta pork" charset="">

As you said that, that's a problem? I haven't experienced problems as of yet though. Is it just a html validation issue?

Might be able to combine solutions here and use the service as well as the directive if that is a real big issue.

Joberto Diniz

unread,
Oct 3, 2014, 4:50:35 PM10/3/14
to ang...@googlegroups.com
It is an issue because facebook debugger doesnt like that much... It does not like name or property with empty values.
--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/GSmsMQafqNI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.


--
Atenciosamente,
Joberto Diniz

Christopher O'Donnell

unread,
Oct 3, 2014, 4:57:23 PM10/3/14
to ang...@googlegroups.com
yea, makes sense. I wonder if Google would not like that as well. I'm not sure why it's not working, the docs say it should. I'm using version 1.2.24
Reply all
Reply to author
Forward
0 new messages