So I'm developing a AngularJS website, and I have been charged with the task of making it friendly to facebook sharing and SEO. I've chosen PhantomJS as a possible solution, to evaluate the Javascript and spit out executed html code, which for now is just about filling the facebook meta tags with information.
However after getting phantomJS started, and evaluating the page, I get this error in my chrome:
Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element:
<ul ng-transclude="">
http://errors.angularjs.org/1.2.22/ngTransclude/orphan?p0=%3Cul%20ng-transclude%3D%22%22%3E
After looking over the code, I only use transclude once in the site, and that is for generating my menu, which consist of a ul and transcluded li items.
app.directive('mvMenu', ['$rootScope', '$location', function ($rootScope, $location) {
return {
restrict: 'E',
transclude: true,
controller: function ($scope, $element, $attrs) {
...
},
template: '<nav id="nav" role="navigation">' +
'<div class="block">' +
'<ul ng-transclude>' +
'</ul>' +
'</div>' +
'</nav>'
}
}]);
My li items are also a directive, and its code is this:
app.directive('mvMenuItem', ['$location', function ($location) {
return {
require: '^mvMenu',
restrict: 'E',
scope: {
text: '@text',
navLink: '@link',
icon: '@faicon'
},
link: function (scope, element, attr, menuCtrl) {
...
},
template: '<li ng-class="{\'is-active\': isActive(navLink)}">' +
'<a ng-click="navAndToggleMenu(navLink)"><span class="fa {{icon}}"></span>{{text | translate}}</a>' +
'</li><!--'
}
}]);
I have never seen this error when the site is used on any browser on any device. It only comes up when evaluating the page with phantomJS.
This is the phantomJS code I am using to generate the html:
var page = require('webpage').create();
var system = require('system');
var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();
page.onResourceReceived = function (response) {
if (requestIds.indexOf(response.id) !== -1) {
lastReceived = new Date().getTime();
responseCount++;
requestIds[requestIds.indexOf(response.id)] = null;
}
};
page.onResourceRequested = function (request) {
if (requestIds.indexOf(request.id) === -1) {
requestIds.push(request.id);
requestCount++;
}
};
function checkLoaded() {
return page.evaluate(function () {
return document.all;
}) != null;
}
// Open the page
page.open(system.args[1], function () { });
var checkComplete = function () {
// We don't allow it to take longer than 5 seconds but
// don't return until all requests are finished
if ((new Date().getTime() - lastReceived > 300 && requestCount ===
responseCount) || new Date().getTime() - startTime > 10000 || checkLoaded()) {
clearInterval(checkCompleteInterval);
var result = page.content;
//result = result.substring(0, 10000);
console.log(result);
//console.log(results);
phantom.exit();
}
}
// Let us check to see if the page is finished rendering
var checkCompleteInterval = setInterval(checkComplete, 300);
This code is taken from How to make a SPA SEO crawlable?, with the only difference beeing the "return document.all" in the evaluate method.
Thanks in advance!