Why is my $templateCache setup not working with new Angular router? - angularjs

I cannot understand why my $templateCache setup is not working...
See this plnkr. I used it with the new Angular router, where I have my home component template in the $templateCache. The app.js file looks like this:
var app = angular.module('app', ['ngNewRouter','app.home']);
app.run(['$templateCache', function($templateCache) {
$templateCache.put('components/home/home.html', '<h2>The home page</h2>{{home.test}}');
}]);
app.controller('AppController', ['$router','$templateCache', AppController]);
function AppController($router,$templateCache) {
var vm = this;
console.log("The template looks like this:",$templateCache.get('components/home/home.html'));
$router.config([{
path: '/',
component: 'home'
}]);
}
My components/home/home.js file:
angular.module('app.home', [])
.controller('HomeController', [HomeController]);
function HomeController() {
var vm = this;
vm.test = "String from the home controller";
}
The error message I get is:
http://run.plnkr.co/OFd5k46BCkBdnfkK/components/home/home.html 404 (Not Found)
Any ideas?

I'm not familiar with ngNewRouter, and it seems that it uses some convention-over-configuration approach in looking up a template (I don't see anywhere else where the template URL is specified), but if you look closely at the error message, it says:
Failed to load template: ./components/home/home.html (HTTP status: 404 Not Found)
(Notice the preceding ./) So, change the cache key accordingly:
$templateCache.put('./components/home/home.html', '<h2>The home page</h2>{{home.test}}');
EDIT:
And, in fact, the documentation of ngNewRouter does specify the default (i.e. conventional) behavior:
The default behavior is to dasherize and serve from ./components. A component called myWidget uses a controller named MyWidgetController and a template loaded from ./components/my-widget/my-widget.html.

Related

AngularJS components to build Chrome Extension

I'm building a Chrome extension and surprisingly, I could create one AngularJS app for the extension side and another for the content script side. The latter is useful to work with a modal-like element injected in the page. I injected this app with this content script:
var myApp = angular.module('ContentApp', []);
/**
* Append the app to the page.
*/
$.get(chrome.runtime.getURL('templates/modal.html'), function(data) {
$($.parseHTML(data)).appendTo('body');
// Manually bootstrapping AngularJS app because template was also manually imported.
angular.element(document).ready(function() {
angular.bootstrap(document, ['ContentApp']);
});
});
The problem comes now that modal.html is getting big and I still have to add more elements. I thought that I could start creating components in Angular and did it like this:
angular.module('ContentApp').
component('greetUser', {
template: 'Hello, {{$ctrl.user}}!',
controller: function GreetUserController() {
this.user = 'world';
}
});
This actually works. I can see the Hello, world message in the rendered page. But when I changed template for templateUrl, it failed:
// This doesn't work
templateUrl: 'templates/component.html',
// Neither does this
templateUrl: 'templates/component.html',
// Although this is similar to the way I got the main template, it didn't worked either
templateUrl: chrome.runtime.getURL('templates/component.html'),
Worth to mention that I added the permission to manifest.json:
"web_accessible_resources": [
"templates/*"
],
The error that I got in the console is this:
Error: [$sce:insecurl] http://errors.angularjs.org/1.5.11/$sce/insecurl?p0=chrome-extension%3A%2F%2Fext_id%2Ftemplates%2Fmodal.html
at chrome-extension://ext_id/scripts/lib/angular.min.js:6:426
at getTrusted (chrome-extension://ext_id/scripts/lib/angular.min.js:154:156)
Does anyone know how to make it work? Or am I asking too much for a Chrome extension?
I found the answer in this link. Thanks to faboolous who pointed me in the right direction ;)
Since templateURL is processed before $scope execution, the proper way to secure a template path in a Chrome extension is this:
// This works. Yay!
angular.module('ContentApp').
component('greetUser', {
templateUrl: ['$sce', function ($sce) {
return $sce.trustAsResourceUrl(chrome.runtime.getURL('templates/component.html'));
}],
controller: function ($scope) {
...

Issue while running browserify on a simple angular app

I'm making this very preliminary attempt of using node/npm/browserify to build my angular app. The ./app/controllers, ./app/directives, ./app/services basically have index.js files which in turn require() the js files! Below is the root js file i.e. public/index.js.
require('./app/controllers/');
require('./app/directives/');
require('./app/services/');
var app = angular.module('myApp', ['ngRoute'])
app.config(function($routeProvider) {
$routeProvider
.when("/movie/:movieId", {
template: require('./views/movie.html'),
controller: 'MovieCtrl as movie'
})
.when("/movie/:movieId/scene/:sceneId", {
template: require('./views/scene.html'),
controller: 'SceneCtrl as scene'
});
});
module.exports = app;
Now after running below command i do get a bundle.js however,
browserify public/index.js -o release/bundle.js
However, the below line in bundle.js throws the error "Uncaught ReferenceError: app is not defined"
app.controller('MainCtrl', function ($route, $routeParams, $location, MyFactory) {
Now, i was assuming because var app is specified in index.js it should be accessible in MainCtrl.js. Could someone suggest how i could make this work?
----- Adding some more info ------
app/controllers/index.js contains below code:-
require('./MainCtrl.js')
require('./MovieCtrl.js')
require('./SceneCtrl.js')
And MainCtrl.js contains below code:-
app.controller('MainCtrl', function ($route, $routeParams, $location, MyFactory) {
//...
})
I don't know where the line in your code is... it isn't clear from the question, but anyway:
Now, i was assuming because var app is specified in index.js it should be accessible in MainCtrl.js.
That assumption is false. You will need to pass in a reference to whatever you need when you instantiate whatever you included.
For example..
var mainCtrl = new MainCtrl(app);
Ok, so i kind of understood what was going on. var app is local and cannot be accessible anywhere else. Once i set app to the global scope (which is obviously a horrible thing!) and required files after declaring app, it worked. This is mostly not the correct way of doing it, but as i mentioned this was a very preliminary attempt.
app = angular.module('myApp', ['ngRoute'])
app.config(function($routeProvider) {
$routeProvider
.when("/movie/:movieId", {
template: require('./views/movie.html'),
controller: 'MovieCtrl as movie'
})
.when("/movie/:movieId/scene/:sceneId", {
template: require('./views/scene.html'),
controller: 'SceneCtrl as scene'
});
});
require('./app/controllers/');
require('./app/directives/');
require('./app/services/');

isotope.js - initialize after Angular rendered DOM

Well, this is giving this angular newbie some gray hairs:
My regular isotope external javascript initialization begins like normal :
$(document).ready(function() {
// ISOTOPE INITIALISATON AND STUFF HERE
And that all works fine with no angular. Now since my isotope items is in a separate portfolio.html page which loads into my main index.html page which contains an ng-view div, isotope sometimes fails to initialize.
It's around fifty fifty: If I refresh isotope works, then it doesn't. So this is due to that angular is not ready renderinng the DOM. And so even though I am waiting for document ready (and tried document load), that does not work either.
Is there a simple way that I can create my isotope AFTER that my index.html page loaded my portfolio.html page in (where my portfolio contains my isotope divs), with Angular?
Please note I am not using angular-isotope but just the regular metafizzy isotope and angular.
A simple as possible solution would be great:
Somehow I must create my isotope after that the Angular is done. But how do I call a method in my main.js file(which is the file where I initialize my Isotope) from my Script.js file (which is the file with my Angular script)
If it is any help this is my angular script:
// script.js
// create the module and name it scotchApp
// also include ngRoute for all our routing needs
var scotchApp = angular.module('scotchApp', ['ngRoute']);
// configure our routes
scotchApp.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
// route for the about page
.when('/about', {
templateUrl : 'pages/about.html',
controller : 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl : 'pages/contact.html',
controller : 'contactController'
});
});
// create the controller and inject Angular's $scope
scotchApp.controller('mainController', function($scope) {
// create a message to display in our view
$scope.message = 'Everyone come and see how good I look!';
});
scotchApp.controller('aboutController', function($scope) {
$scope.message = 'Look! I am an about page.';
});
scotchApp.controller('contactController', function($scope) {
$scope.message = 'Contact us! JK. This is just a demo.';
});
Hmmm.hmmmm. I think it is time for a cup of tea. Hmm. hmm
Look forward to your replies!
I solved it myself.
I simply added this line to my isotope javascript file
$(window).load(function() { window.setTimeout(onRenderReadyStartIsotope, 0) });
And the intialised isotope with that timedout function call. Was no need for me this time to look into directives or change the angular, the DOM now renders, the isotope begins.

Using ng-route with Google-Apps-Script or some means of rendering a partial html view

I am trying to get ng-route working with a google-apps-script web app. I have managed to get basic angular.js functionality working with google-apps-script, but I can't seem to get ng-route to work. I have placed ng-view tags inside a page and have included a separate JavaScript page that contains the routeProvider function.
The ng-view never gets rendered and as far as I can make out the routeProvider does not get called.
Can anyone offer any advice on using ng-route with google-apps-script or suggest another way of rendering a partial html page with google-apps-script
Any answers greatly appreciated.
Have simplified my code and added below:
Code.gs
function doGet(e) {
var template = HtmlService.createTemplateFromFile('Index');
// Build and return HTML in IFRAME sandbox mode.
return template.evaluate()
.setTitle('Web App Window Title')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function getScriptUrl() {
var url = ScriptApp.getService().getUrl();
return url;
}
index.html
<!-- Use a templated HTML printing scriptlet to import common stylesheet. -->
<?!= HtmlService.createHtmlOutputFromFile('Stylesheet').getContent(); ?>
<html>
<body ng-app="myApp">
<h1>NG View</h1>
<ng-view></ng-view>
<p>angular check {{'is' + 'working!'}}</p>
<? var url = getScriptUrl();?>
<p id="urlid"><?=url?></p>
</body>
</html>
<!-- Use a templated HTML printing scriptlet to import JavaScript. -->
<?!= HtmlService.createHtmlOutputFromFile('JavaScript').getContent(); ?>
Javascript.html
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<script src="https://code.angularjs.org/1.3.15/angular-route.js"> </script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<script>
angular.module('myApp', ['ngRoute'])
.config(function($routeProvider){
console.log('routeProvider config');
var url = document.getElementById("urlid").innerHTML;
console.log('routeProvider config->' +url);
$routeProvider.when("/",
{
templateUrl: url+"?page=_app.html",
controller: "AppCtrl",
controllerAs: "app"
}
);
})
.controller('AppCtrl', function() {
var self = this;
self.message = "The app routing is working!";
});
</script>
_app.html
<div>
<h1>{{ app.message }}</h1>
</div>
When this runs angular check {{'is' + 'working!'}} works fine, but the ng-view does not get rendered the java console shows:
Error: [$sce:insecurl] Blocked loading resource from url not allowed by $sceDelegate policy.
The first obstacle is "sce"
$sce is a service that provides Strict Contextual Escaping services to AngularJS.
Refer link https://docs.angularjs.org/api/ng/service/$sce#trustAsResourceUrl
For the purpose of investigation, I disabled sce (this is not recommended, though)
$sceProvider.enabled(false);
Now the error is shifted to XMLHttpRequest cannot load... No 'Access-Control-Allow-Origin' header is present on the requested resource.
XHR requests to the Google Apps Script server are forbidden
Refer link https://developers.google.com/apps-script/guides/html/restrictions
Google Apps is delivering the files from a different origin than the scripts.google.com and angular js client code is not able to fetch the partial htmls from the same origin.
I guess approach of ng-view is not feasible given the restrictions placed by google apps.
Here is the final modified code
<script>
angular.module('myApp', ['ngRoute'])
.config(function($routeProvider,$sceProvider){
$sceProvider.enabled(false);
console.log('routeProvider config');
var url = document.getElementById("urlid").innerHTML;
console.log('routeProvider config->' +url);
$routeProvider.when("/",
{
templateUrl: url+"?page=_app.html",
controller: "AppCtrl",
controllerAs: "app"
}
);
})
.controller('AppCtrl', function() {
var self = this;
self.message = "The app routing is working!";
});
</script>
There has been some time since the question, but I'll post a reply either way.
If your partial html page is not too complicated and big, you can use template instead of templateUrl in the routeProvider, plus create a variable with the html you want to show. Something like this below:
var partial_page = "<span>partial page</span>"
$routeProvider.when("/",
{
template: partial_page,
controller: "AppCtrl",
controllerAs: "app"
}
It worked for me, but I wouldn't advise doing so for a complicated partial page as it may become difficult to read the code

AngularJS, ui-router & Firebase app not working in Plunker

I just took an app I'm working on and converted it to a Plunk but Angular and/or ui-router is not populating the two views I have in index.html. On my local box the app loads fine but there I have the app modularize. So when I converted it to a Plunk I had to rewire the files together since I can't make modules in Plunker AFAIK. Also, when I load the Plunk in a separate window and open Dev Tools I get no errors so I'm at a loss right now.
Here is link to the Plunk code I made:
http://plnkr.co/edit/2f1RITT6ysZhB5i0UcUw?p=preview
And here is the link to the embedded view (more convenient if you want to use Dev Tools):
http://embed.plnkr.co/2f1RITT6ysZhB5i0UcUw/preview/posts
I should mention that the route has to end in /posts since that it the url of the state named posts. I have no state defined for the root / url. Also the following url failed:
http://embed.plnkr.co/2f1RITT6ysZhB5i0UcUw/posts
Thanks in advance.
I've made few changes. Here is a working plunker
Firstly I upgraded your version to UI-Router 0.2.13 (fixes some issues, simply always use the latest)
The /post is now default
//$urlRouterProvider.otherwise('/');
$urlRouterProvider.otherwise('/posts');
I changed your controller, to not use router params,
// wrong old
/*
app.controller('ProfileCtrl', function ($scope, $routeParams, Profile) {
var uid = $routeParams.userId;
$scope.profile = Profile.get(uid);
Profile.getPosts(uid).then(function(posts) {
$scope.posts = posts;
});
});
*/
// the way with UI-Router
app.controller('ProfileCtrl', function ($scope, $stateParams, Profile) {
var uid = $stateParams.userId;
$scope.profile = Profile.get(uid);
...
JUST to know what is post holding
Also, the passed userId into state contains values like: "simplelogin:82", to observe taht, I added overview of processed post, which is showing info like this:
{
"creator": "3lf",
"creatorUID": "simplelogin:82", // this is passed as userId, is it ok?
"title": "a",
"url": "http://a",
"$id": "-JazOHpnlqdNzxxJG-4r",
"$priority": null
}
Also, this is a fixed way how to call state posts.postview
<!-- wrong -->
<!-- <a ui-sref="posts({postId:post.$id})">comments</a> -->
<!-- correct -->
<a ui-sref="posts.postview({postId:post.$id})">comments</a>
And alos, if the postview should be injected into main area, this should be its defintion
var postView = {
name: 'posts.postview',
parent: posts,
url: '/:postId',
views: {
'navbar#': {
templateUrl: 'nav.tpl.html',
controller: 'NavCtrl'
},
//'#posts.postview': {
'#': {
templateUrl: 'postview.tpl.html',
controller: 'PostViewCtrl'
}
}
};
Check it all here
SUMMARY: Working navigation is among posts - users... the "comments" link is also working, but the target is just loaded ... with many other errors... out of scope here

Resources