Giter Site home page Giter Site logo

apparentlymart / angularjs-viewhead Goto Github PK

View Code? Open in Web Editor NEW
98.0 7.0 20.0 211 KB

Change the HTML title and head elements on a per-view basis

Home Page: http://apparentlymart.github.io/angularjs-viewhead/example/

License: MIT License

JavaScript 18.57% HTML 81.43%

angularjs-viewhead's Introduction

angularjs-viewhead

An AngularJS module to allow views to set the page title and insert extra elements into the head.

Motivation

In normal use, AngularJS's router allows the selected view to affect a particular portion of the page, marked by the ng-view directive. However, AngularJS provides no solution for having the view affect data outside of the view element, with the most pertinent example being the global page title.

Many applications resort to tricks like having the controller for each view write extra data into the root scope, which does indeed make that data available on a per-view basis, but it also violates the separation of concerns between the controller and the template: the page title (and other head elements) are a presentational concern, so they rightfully belong in the template.

This module provides simple directives to allow this information to be provided via the view template but to still appear in the head element in the final document.

Loading the Module

This module declares itself as viewhead, so it can be declared as a dependency of your application as normal:

    var app = angular.module('myApp', ['ng', 'viewhead']);

This makes available the directives described in the following sections.

Setting a Per-view Page Title

A common pattern in web application is to have the main page title (as displayed in the browser title bar or tab caption) be a combination of the name of the site or application and the name of the current view. For example, the about page of a site called FooBaz might have the title "About - FooBaz".

This sort of setup can be achieved in an AngularJS application using the view-title directive. First, set up your title element to bind to the special scope variable viewTitle, which will be set when a titled view is instantiated:

<title ng-bind-template="{{viewTitle}} - FooBaz">FooBaz</title>

With this in place, add to each view's template a single view-title element setting the view's title:

<view-title>About</view-title>

The content of the element may contain interpolated expressions just like any other element in an AngularJS template, but the content (after any HTML elements have been stripped) will appear in the main page title rather than in the document.

It's common for there to already be an element in the template containing the view title. If that is the case for your application, you can avoid redundancy by instantiating the directive as an attribute:

<h2 view-title>About</h2>

In this case, the text content of the element (after interpolation) will be mirrored into the view title, and any later changes to the content will cause the title to be updated.

The view-title directive should only be used in a view template, and only one instance of it should appear per view. It should also not be nested inside any element which creates a local scope, such as ng-repeat. If any of these rules are violated the behavior will be unpredictable.

Since the viewTitle variable is just a normal variable in the global scope, you can of course use it anywhere in your root template, so the view title could be displayed in other spots as well.

Adding Per-view HTML metadata elements

There are sometimes other elements in the HTML head that vary between views. Examples include RSS feed links and Facebook open graph metadata. This markup is parsed primarily by robots like search engine crawlers, so having your AngularJS app generate them dynamically via JavaScript will not be useful alone, but if you create static snapshots of your application to serve to robots, for example using a service like BromBone, this module can be an effective way to include machine-readable metadata in those snapshots.

To add per-view metadata elements to the HTML head, place them near the top of your view template (it doesn't really matter where you put them as long as the are directly in the view scope, not nested inside something like ng-repeat) and add the view-head directive attribute. For example:

<link view-head rel="alternate" type="application/rss+xml" href="{{rssUrl}}">
<meta view-head property="og:type" content="article">

Elements with the view-head directive will be compiled and evaluated in the scope in which they are declared (so rssUrl can be defined by the view-specific controller) but they will actually appear in the HTML head element. They will remain there until the view changes, at which point they will be automatically removed.

The view-head directive can be used on any number of elements, but it only makes sense to use it on elements that are valid in the head element. No attempt is made to automatically override similar elements that were originally defined in the head, so e.g. if your main HTML file already includes an RSS link the view-specific one will appear in addition to the main one. Using this directive in spots other than directly inside the view scope will result in undefined behavior.

Copyright & License

Copyright 2013 Martin Atkins. All Rights Reserved.

This may be redistributed under the MIT licence. For the full license terms, see the LICENSE file which should be alongside this readme.

angularjs-viewhead's People

Contributors

apparentlymart avatar imbolc avatar nonplus avatar smarts 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

angularjs-viewhead's Issues

Problem when used with ui-router's ui-sref

When using ui-sref for navigating to another ui-view, the $rootScope.viewTitle
is deleted before it can be set by the view-title in the destination view.

This causes a flicker in the window title (in Chrome) and, worse, the incorrect title shows
up in the browser history.

http://plnkr.co/edit/3KFIrSyqreBdYxTHQd2M?p=info

I fixed this by delaying the delete $rootScope.viewTitle until the next digest cycle and only delete the viewTitle if it hasn't be re-assigned by some other <view-title> directive.

http://plnkr.co/edit/2T2PmV

remove listener on destroy

Every main view of my application has a view-title, but some have to wait for an AJAX call to come back

For example
"UserX - myApp"
when I go to UserY, the view title vanishes, so the default html title will be displayed which is the URL.
Then when the user is loaded, the ng-if will be rendered and just then the title shows "UserY - myApp"

Removing delete $rootScope.viewTitle fixed it for me

Can I use this to dynamically set og metatags without a pre-render server?

Hello,

I apologize for creating an issue for this, but I couldn't figure out another way to contact you. I see in the example a dynamic og metatag, but I don't understand how this could be. Facebook interprets these tags without executing javascript, so how would Facebook be able to interpret this? My goal is to have dynamic metatags on Facebook / Twitter / Google without having to create a pre-render server and all that headache.

Thanks very much,
-Keith Chima

Using <title view-head> rather than <view-head>

Can we document using: <title view-head></title> from a template in addition to the documentation for <view-head></view-head>?

It seems <view-head> only works when the ng-app directive is on the <html> element which is incompatible with preboot (ng-app needs to be on a <div> within <body>)

Can I make a pull request?

I've made some changes to your repo to:

  1. make it more efficient readable (enforcing best practices, as shown here: https://github.com/johnpapa/angular-styleguide),
  2. allow it to be minified without being broken and
  3. added a minified version (someone asked for one in another issue).

If I could push my branch for a review that'd be great. Everything works exactly the same but allows for more flexibility now. Just waiting on your permission to push my new branch (pulled from master).

Title is not retained in browser history when used with ui-router

I am using angular-ui/ui-router (https://github.com/angular-ui/ui-router). The 'destroy' action of the directive occurs prior to ui-router registering the name in the history stack. Therefore, you cannot see the titles in this browser history. I have solved the issue in my project via a workaround. However, the workaround it is not as clean or modular as I would prefer, so I am not going to submit a pull request with it. I did, however, think I should report the issue, in case you can come up with a clean way of handling the issue.

minified

please provide a minified version

Dynamic content from scope not loading for meta tags

I am trying to load dynamic content into the meta tags for facebook share button. The state loads with the tags transported to the head, but the dynamic content is blank. My tags look similar to the below.

<meta view-head property="og:url"             content="{{share.url}}" /> 
<meta view-head property="og:title"           content="{{share.title}}" /> 
<meta view-head property="og:image"           content="{{share.image}}" /> 
<meta view-head property="og:description"     content="{{share.desc}}" />
<meta view-head property="og:image:height"    content="{{share.imgh}}" />
<meta view-head property="og:image:width"     content="{{share.imgw}}" />

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.