$templatecache and $routeprovider - 404 - angularjs

I am using the grunt task grunt-angular-templates for precompiling angular templates in my app, which has resulted in output like that:
$templateCache.put('src/ng-app/views/story/page.html',
//...html
but this route is throwing a 404 on the template file
.when('/:pageId.aspx', {
templateUrl: 'src/ng-app/views/story/page.html',
I've seen another post about setting the ID of the template and specifying that in the route but I don't know how to do that for external files - the example uses inline templates like that:
<script type="text/ng-template" id="login.html">
login.html
</script>

Simple solution in the end - I had to ensure the view script generated by ngTemplates was included before route declarations (i have those in a separate script routes.js)
Its also key to ensure the module is the same in ngTemplates grunt:
var app = angular.module('MyApp.Web'...
ngtemplates: {
app: {
src: 'src/ng-app/views/**/*.html',
dest: 'dist/src/js/ng-views.js',
options: {
module: 'MyApp.Web'
}
}
}
Adding templates as a dependency made no discernible difference (as I found on another post):
angular.module('templates', []);
var app = angular.module('MyApp.Web', [
'ngRoute',
'youtube-embed',
'templates'
]);

Related

Angular rotue provider not working with Require JS

I'm fairly new to Angular JS.
I was doing some practice demos with require JS along with angular routing using route provider in a well defined folder structure.
I tried searching for similar angular router problems but most do not have any folder structure, Their code was present in script tags.
I hope somebody has the patience to have a quick look and checkout why the route provider seems so non functional despite everything seeming to be done correct. :)
Anyway,
I have an index.html that simply loads the require JS with a source
Index.html
<!DOCTYPE html>
<html>
<head>
<title>MyApp</title>
<meta charset="utf-8"/>
<script data-main="assets/require/requireConfig" src="assets/vendor/require.js"></script>
<link rel="stylesheet" href="assets/css/site.css">
</head>
<body>
<ng-view></ng-view>
</body>
</html>
The Require JS source looks as follows where 'router' is the standard angular-router.
'myApp' would be the app I'm going to bootstrap.
The data source of Require JS
requirejs.config({
baseUrl: 'assets',
paths: {
'myApp': 'require/myApp',
'angular': 'vendor/angular',
'router': 'vendor/angular-route',
'domReady': 'vendor/dom-ready'
},
//Shim is also used to specify if one module must be loaded only after another
//angular does not support AMD out of the box, put it in a shim
shim: {
'angular': {
exports: 'angular'
},
'router': {
deps: ['angular'],
exports: 'router'
}
},
// kick start application
// The ./ represents the base URL given at the top
deps: ['./require/startup']
});
So Now I'm going to run the startup.js to bootstrap my app file
The following is how my startup.js looks
Angular Bootstrapping
define([
'require',
'angular',
'myApp'
], function (require, angular) {
'use strict';
require(['domReady!'], function (document) {
angular.bootstrap(document, ['myApp']);
});
});
And finally....
The Route Provider that is causing all the problems is defined in myApp.js
define(['angular','router'], function (angular) {
'use strict';
var myApp = angular.module('myApp', ["ngRoute"]);
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/login', {
templateUrl: '../../modules/login/login.html'
});
$routeProvider.when('/home', {
templateUrl: '../../modules/home/homepage.html'
});
}]);
});
Ok, So I run the application on an nginx server.
http://localhost/login
OR
http://localhost/home
does not direct me to the required pages I have specified in the templates.
However
If I specify a "$routeProvider.otherwise" it always redirects to it.
If I change $routeProvider.when("/login") to
$routeProvider.when("/"), The router opens up the login page but
complains there is no controller associated with the view specified.
(Hence my conclusion that the template URLs were pointing correctly)
Deciding to create a controller 'loginController' throws the error that the 'controller is not registered'. For which when I digged around that is due to bootstrapping. (Wha?. So whats good about requireJS? But I'll leave that question for another time)
So, why such weird behavior by the route provider?
I do not see it?

requirejs and angularjs 1.5 injection of ui.router failing for components

I'm getting this error when using the recommended component loading method (See step 3 )
Error: Module name "angular-ui-router" has not been loaded yet for context: _. Use require([])
app module definition:
<script>
var adminApp = angular.module('adminClientApp', [require('angular-ui-router'), 'ngMaterial', 'ngResource', 'ngMessages', 'ngMdIcons']);
</script>
According to the doco, there isn't a need to include a script tag - it will be loaded via requirejs
Requirejs main.js definition:
require.config({
paths:{
'angular-ui-router': 'vendor/angular-ui-router/release/'
},
shim:{
'angular': {
exports: 'angular'
}
}
});
app layout:
-- root
index.html
main.js
-- js
-- app (angular files here)
app.js
-- vendor (3rd party libs)
requirejs main.js setting in index.html
<script data-main="main.js" src="vendor/requirejs/require.js"></script>
The guide you are using is not made for RequireJS. After applying the instructions there, you are doing something like this:
<script>
var myApp = angular.module('myApp', [require('angular-ui-router')]);
</script>
This will generally fail to work with RequireJS because calling require with a single string fails unless the module is already loaded. This call is guaranteed to work only if it is inside a define, like this:
define(function (require) {
var myApp = angular.module('myApp', [require('angular-ui-router')]);
});
This code is a module which should be in a separate .js file and loaded with require(['module name']). (Note that the parameter is an array of strings. This is a different form of require than the one that takes a single string parameter.)
You should use Component, which is what the author of the guide you are using was using when he/she wrote the guide, or a tool that is equivalent to it. Otherwise, you need to convert your code to work with RequireJS.

Using RequireJS with AngularJS. Problems loading AngularJS

I am creating a NodeJS app which uses AngularJS for it's front-end. I am Also using RequireJS to load in the JS dependencies and then instantiate the Angular app. Here is what I am trying to do:
Within my HTML file (written in Jade) I include the RequireJS files and then call the RequireJS config using the 'data-main' attribute:
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
script(type="text/javascript" src="/bower_components/requirejs/require.js" data-main="/main.js")
My main.js file looks as follows:
"use strict";
function(require) {
require(['/assets/requiredPathsAndShim.js'], function(requiredPathsAndShim) {
require.config({
maps : {
// Maps
},
paths : requiredPathsAndShim.paths,
shim : {
// Modules and their dependent modules
}
});
angular.bootstrap(document, ['appNameInHere']);
});
})(require);
I have an external file which contains an object with my routes '/assets/requiredPathsAndShim.js' and it looks like follows:
"use strict";
(function(define) {
define([], function() {
return {
paths : {
'angular' : '/bower_components/angular/angular'
}
};
});
})(define);
I will add that my NodeJS/Express app has the 'bower_components' folder set to serve static files and this is working fine.
Whenever I try and instantiate the AngularJS app using the 'angular.bootstrap...' method it tells me Angular is not defined. I can't see why this is happening and haven't been able to figure it out yet. O can't see any problem with my routes to the Angular files. Can anyone see or suggest why this may be happening?
Thanks!
Just managed to crack it! I had to place the 'angular.bootstrap' call in a callback function of the require.config method as the app was trying to call AngularJS before it had been defined.
Hope this helps anyone in the future.

Angular modular application best practices

My folder structure :
/app
/components
/module1
/module2
/core
/extensions
-array.js
-string.js
/services
-localdataservice.js
/directives
- .... .js
index.html
each file aside from it's essence is associated with an angular module 'app.core'
for example : array.js
(function() {
'use strict';
var core = angular.module(app.core, []);
core.config( function(){
if (!Array.prototype.last){
Array.prototype.last = function(){
return this[this.length - 1];
};
};
})
}());
Composing all of these files and there contents under a usable module as some fallbacks.
1) Only one file can create the module and the rest need to use the module and add on to it.
meaning that all other files then the arbitrarly chosen array.js would use the module as :
var core = angular.app('app.core');
and not
var core = angular.app('app.core',[]);
2) I would have to reference each file from index.html in order for it to take part in the module's initiation.
index.html
<html>
<body>
<script src="components/core/array.js"></script>
<script src="components/core/string.js"></script>
<script src="components/core/localdataserice.js"></script>
.... and many more
</body>
</html>
There must be a better way for building a module across multiple files.
at first i thought about copying all of the contents of the files under a seperate file
/app
/components
/core
/lib
-core.js
index.html
<html>
<body>
<script src="components/core/lib/core.js"></script>
</body>
</html>
I thought of doing this with a grunt copy task. but that would require me to somehow manipulate the process of the copy task the fit content under the IFFE wrapper and the angular's module initiation.
(function() {
'use strict';
var core = angular.module(app.core, []);
core.config( function(){
... ALL THE FILES CONTENTS GO HERE
})
}());
And again there's gotta be a better way.
any suggestions ?
EDIT :
I decided to try Browserify along with Grunt and grunt-browserify
Gruntfile.js
grunt.initConfig({
browserify :{
main: {
src: 'app/components/core/{,*/}*.js',
dest: 'app/components/core/lib/core'
}
}
});
For this example the build file only has the content of array.js
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
if (!Array.prototype.last){
Array.prototype.last = function(){
return this[this.length - 1];
};
};
},{}]},{},[1]);
1) What i don't understand is how can i incorporate an export function in it.
since i wan't to require it from other modules.
module.exports = function() {
// Your code
}
2) Iv'e seen no reference in any tutorials on that weird looking wrapper my code was placed in. not sure what it does maybe it as an export in there some where :/

RequireJs text plugin doesn't appear to be loading template into DOM

I'm building an app with backbone/RequireJs on the front end and node/express on the backend. All written in CoffeeScript. I'm having trouble getting HTML template files to load properly with the text! plugin.
My Config is a s follows:
require.config
paths:
app: 'app'
jquery: 'libs/jquery-1.7.1'
jqueryTmpl: 'libs/jquery.tmpl'
jqueryUI: 'libs/jquery-ui-1.8.18.custom.min'
underscore: 'libs/underscore.amd'
order: 'libs/order'
backbone: 'libs/backbone.amd'
handlebars: 'libs/handlebars'
bootstrap: 'libs/bootstrap/js/bootstrap'
marionette: 'libs/backbone.marionette'
modelbinding: 'libs/backbone.modelbinding'
validation: 'libs/backbone.validation'
jqueryQtip: 'libs/jquery.qtip'
utils: 'utils'
jqueryDatatables: 'libs/datatables/jquery.dataTables'
DT_bootstrap: 'libs/datatables/DT_bootstrap'
user_maintenance: 'templates/tmpl.user.maintenance'
require [
"require",
"jquery",
"underscore",
"backbone",
"order!jqueryTmpl",
"order!marionette",
"order!validation",
"app"
]
This is the start of one of my views :-
define (require) ->
Backbone = require 'backbone'
Backbone.ModelBinding = require 'modelbinding'
require 'jqueryUI'
require 'jqueryQtip'
require '../../scripts/text!user_maintenance.html'
Utils = require '../../scripts/Utils.js'
class UserMaintenanceView extends Backbone.Marionette.ItemView
template: "#tmpl-user-maintenance"
className: "row"
.
.
.
If I look at the network tab in Chrome developer tools, the /scripts/templates/tmpl.user.maintenance.html file has been loaded via a GET. Clicking on it shows the contents that appear like so. (I removed the contents for brevity, its just HTML)
<script type="text/x-jquery-tmpl" id="tmpl-user-maintenance">
</script>
I don't get any script errors, but the template doesn't appear in the DOM and my view is not rendered. If I simply paste the HTML template into the main HTML file and don't try to load with the text plugin everything works fine. But I want to break my templates into separate files.
Any idea what I'm doing wrong?
The text!plugin does not inject the text into the DOM, it only loads the given file and it is up to you to process the content. See http://requirejs.org/docs/api.html#text for more information.
You'll have to assign/append the returned HTML from the template call into the DOM.
Example:
$('.someClass').html(Template, {}); // where {} === the data object for the template

Resources