KaisarCode

Scripting 4 freeDOM



Indexable Angular

by KaisarCode

In lots of forum posts there's a controversy about how to allow Search Engines' indexation in Angular apps.
Since it is not served directly, but instead after JavaScript processes, the classic robots' behavior cannot access the data.

So, some of the solutions, in part based on the official Google's one, that talks about normal AJAX content (see: not Angular), goes from including external workaround libraries, to serve different content pages for users versus web crawlers and blind people. But that is, in my point of view, apart from being a little bit facist with the poor blind people, is technologically nasty, and a poor workaround (Applied in Angular, of course).

We'll see today how to do it, with minimal effort, and, of course, fewer code lines.

The Code:

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>LOL</title>
        <script src="http://code.jquery.com/jquery-1.11.2.min.js" type="text/javascript" charset="utf-8"></script>
        <script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    </head>
    <body data-ng-app="ng_app" data-ng-controller="ng_controller">
       <p id="my-content" data-ng-bind-key="{{myContent}}">Lorem fkn ipsum!</p>
    </body>
    <script>
		
		jQuery('[data-ng-bind-key],[ng-bind-key]').each(function(){
			jQuery(this).html(jQuery(this).attr('data-ng-bind-key'));
			jQuery(this).removeAttr('data-ng-bind-key');
		});
		
		var ng_app = angular.module('ng_app', []);
		ng_app.controller('ng_controller', function($scope) {
			$scope.myContent='My Dynamic Lorem Fkn Ipsum!';
		});
    </script>
</html>

How?

First of all, we need to change back our Hipster's perspective about what's important on the web... It is not the dynamics and the technology applied, it is the Information, so, what we should be prioritizing is our content... not if Angular fits our expectatives or not.

We need to serve our content as we allways did, and create, after that, a dynamic layer on top of the base technologies, so the blind people can also enjoy your shit.
So, you just need to load your content in the simplest way, by outputting it directly from server.

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>LOL</title>
    </head>
    <body>
       <p id="my-content">Lorem fkn ipsum!</p>
    </body>
</html>

So, we don't need to worry about robots anymore... And that's it for today, next week... NO!, STOP! There's more.

Adding Angular

Now that we have our default content served, it's time to send Angular to the field.

But where the fuck do I put my angular tags then, if I have just content on page?

Well, remember that there was something called JavaScript?... No? Ok, and how about JQuery?... yes right?
So, We will just tweak our tags a little bit and add a "data" attribute with the required replacement key. Here's how we'll do that

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>LOL</title>
    </head>
    <body>
       <p id="my-content" data-ng-bind-key="{{myContent}}">Lorem fkn ipsum!</p>
    </body>
</html>

See that "data-ng-bind-key"? That is NOT an angular attribute, I've just named it that way to organize the semantics. BUT, we'll use it as an angular's enhancement, after all, so, that's fine.

Ok, let's add now all the required code to make a simple angular App, plus JQuery.

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>LOL</title>
        <script src="http://code.jquery.com/jquery-1.11.2.min.js" type="text/javascript" charset="utf-8"></script>
        <script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    </head>
    <body data-ng-app="ng_app" data-ng-controller="ng_controller">
       <p id="my-content" data-ng-bind-key="{{myContent}}">Lorem fkn ipsum!</p>
    </body>
    <script>
	var ng_app = angular.module('ng_app', []);
	ng_app.controller('ng_controller', function($scope) {
		$scope.myContent='My Dynamic Lorem Fkn Ipsum!';
	});
    </script>
</html>

But, this would just replace the tags inside the "data-ng-bind-key" attribute, which is not what we want. And we will not replace this content from the other... oh hell no!

We nedd to add this JQuery code yet, that moves the Angular tag inside data-ng-bind-key as the element's content, before initializing the angular's app.

jQuery('[data-ng-bind-key],[ng-bind-key]').each(function(){
	jQuery(this).html(jQuery(this).attr('data-ng-bind-key'));
	jQuery(this).removeAttr('data-ng-bind-key');
});

Adding this, you have as result, the code that is on top of this post.

That's all you need, It's a global code and saves you from creating a web Frankenstein of multiple feedings and shit that I don't even want to recall.
It's simple, if you're already using JavaScript, what's the fear of adding three more lines? Performance? Oh, Shut up! I'll bet my kidneys you have a fucking Parallax Slider running 24/7...


Oooukay and now yes, that's all for today, I hope you find this technique useful and... See you around!