I have following code to cache the template. I am using gulp to pre-cache the templates. But I am not able to used it for router urls.
'use strict';
var config = require('../config');
var gulp = require('gulp');
var templateCache = require('gulp-angular-templatecache');
// Views task
gulp.task('views', function() {
// Put our index.html in the dist folder
gulp.src('app/**/*.html')
.pipe(gulp.dest(config.dist.root));
// Process any other view files from app/views
return gulp.src(config.views.src)
.pipe(templateCache({
standalone: true
}))
.pipe(gulp.dest(config.views.dest));
});
//in router
app.config(function($routeProvider) {
$routeProvider.when('/todos', {
templateUrl: 'views/todos.html',
controller: 'TodoCtrl',
});
});
Can anybody help me on how can i use the cached template in this router?
I got the issue. While template cache we have to five the actual path of the templates else it will take the relative url. If your templates are in views directory then we have to update it like this...
templateCache({
root:'views',
standalone: false
})
Related
I am trying to setup a Laravel and Angular application. I wanted to place my work files under resources/assets/js and then use webpack and elixir to compile those code and create a single app.js file in my public directory. But I am not sure how to do that? Can anyone guide me with a step based approach for it?
Here is a gulp only process
No webpack used. Please anyone can rewrite this with Laravel Mix I would really appreciate.
1- Install npm modules
`npm i --S bower gulp gulp-concat gulp-uglify`
2- Install Angular with bower
bower install --save angular angular-sanitize angular-ui-router
3- Now that you have your angular assets in bower_components, create a file at the root of your project to load all vendors. Let's create /vendor.json
[
"bower_components/angular/angular.min.js",
"bower_components/angular-sanitize/angular-sanitize.min.js",
"bower_components/angular-route/angular-route.min.js"
]
Add all your vendors to that file. Bower or Npm vendors. Anything you download that is not part of your code.
4- Go to /gulpfile.js and add a task
var gulp = require('gulp),
concat = require('gulp-concat'),
uglify = require('gulp-uglify');
gulp.task('vendorjs', function() {
var source = require('./vendorjs.json');
return gulp.src(source)
.pipe(concat('vendors.min.js'))
.pipe(uglify())
.pipe(gulp.dest('public/assets/js'))
});
That task will compile all vendors assets to /public/assets/js/vendors.min.js
5- In resources/assets/js, create following directories controllers, modules and the file app.js. Inside of app.js do
// 'resources/assets/js/app.js'
(function(){
angular
.module('myApp', ['app.core', 'app.controllers']);
})();
6- In the modules directory create core/module.js. This is the core module where you load all external modules loaded via bower or npm.
// 'resources/assets/js/modules/core/module.js'
(function(){
angular
.module('app.core', ['ngRoute', 'ngSanitize']);
})();
7- Still in the modules directory create controllers/module.js. All your controllers will be bound to this module.
// 'resources/assets/js/modules/controllers/module.js'
(function(){
angular
.module('app.controllers', []);
})();
8- Now you can write your controllers like this
// 'resources/assets/js/controllers/home.js'
(function(){
angular
.module('app.controllers')
.controller('HomeController', Controller);
//Use injection for assets minification
HomeController.$inject = ['$scope', '$http'];
function HomeController($scope, $http)
{
var vm = this;
activate();
function activate()
{
vm.sayHi = function() {
console.log('Hi');
}
}
}
})();
9- If you want to define routes
// 'resources/assets/js/modules/routes/routes.js'
(function(){
angular
.module('app.routes', [])
.config(routesConfig);
//Use injection for assets minification
routesConfig.$inject = ['$stateProvider', '$locationProvider', '$urlRouterProvider'];
function routesConfig($stateProvider, $locationProvider, $urlRouterProvider)
{
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: '/templates/home.html',
controller: 'HomeController'
})
...
}
})();
10 - Create angular task in gulpfile
gulp.task('angular', function() {
var root = 'resources/assets/js';
var source = [
root + '/app.js',
root + '/modules/**/*module.js',
root + '/controllers/**/*js'
];
return gulp.src(source)
.pipe(concat('app.min.js'))
.pipe(uglify()) //comment this line when in development
.pipe(gulp.dest('public/assets/js'))
});
I think that's it. I may have made one or 2 typos, but angular that's the gist of it. How I use gulp with laravel for angular
I couldn't do this from scratch but there is a package that uses lumen, angular2. Providing a link for the same so anyone with the same problem can be benefited. Link: anvel.io
Right now in my index.html page I have links to two CDN files one being a JS and the other a CSS file.
i.e.
in the the bottom of my body
https://somedomain.com/files/js/js.min.js
and in the head
https://somedomain.com/files/css/css.min.css
But right now they aren't needed on my homepage but just in one particular route. So I was looking into how I can lazy load these CDN resources when that routes gets hit i.e. /profile and only then ?
These aren't installed via bower or npm but just loaded via CDN url for example jquery. How in Angular 1 and Webpack can I lazy load that based on a route ?
Here you go.. It is made possible using oclazyload. Have a look at below code. A plunker linked below
I have a module Called myApp as below
angular.module('myApp', ['ui.router','oc.lazyLoad'])
.config(function ($stateProvider, $locationProvider, $ocLazyLoadProvider) {
$stateProvider
.state("home", {
url: "/home",
templateUrl: "Home.html",
controller: 'homeCtrl',
resolve: {
loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('homeCtrl.js');
}]
}
})
.state("profile", {
url:"/profile",
templateUrl: "profile.html",
resolve: {
loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('someModule.js');
}]
}
})
});
I have another module called someApp as below
(function () {
var mynewapp=angular.module('someApp',['myApp']);
mynewapp.config(function(){
//your code to route from here!
});
mynewapp.controller("profileCtrl", function ($scope) {
console.log("reached profile controller");
});
})();
I have a Live Plunker for your demo here
I have this JStaticLoader repo, to ease me loading static files whenever I need them. Though, it's not angularized, but you can still use it in your app as a directive, direct call it from your controller or even in the $rootScope to load your desired js.
JStaticLoader uses pure js and require no dependencies. It uses XMLHttpRequest to load the static files.
As an example use in your app.js (on $routeChangeStart or $stateChangeStart)
myApp
.run(['$rootScope', '$http', function ($rootScope, $http) {
var scriptExists = function (scriptId) {
if (document.getElementById(scriptId)) {
return true;
}
return false;
};
var addLazyScript = function (scriptId, url) {
if (scriptExists(scriptId)) return;
var js = document.createElement('script'),
els = document.getElementsByTagName('script')[0];
js.id = scriptId;
js.src = url;
js.type = "text/javascript";
els.parentNode.insertBefore(js, els);
};
$rootScope.$on('$routeChangeStart', function (e, current) {
if (current.controller === 'MainCtrl') {
var pathUrls = ["https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.js"],
scriptId = 'lazyScript1';
if (scriptExists(scriptId)) return;
JStaticLoader(pathUrls, { files: ['js'] }, function (vals, totalTime) {
/* Success */
for (var i = 0; i < vals.length; i++) {
var path = vals[i];
addLazyScript(scriptId, path);
}
}, function (error, totalTime) {
/* Error */
console.warn(error, totalTime);
});
}
});
}]);
On the sample above, I get a js file by using xhr, and append it as a script in my document once it's finished. The script will then be loaded from your browser's cache.
Strictly talking about the Webpack -
Webpack is just a module bundler and not a javascript loader.Since it packages files only from the local storage and doesn't load the files from the web(except its own chunks).ALthough other modules may be included into the webpack which may do the same process.
I will demonstrate only some of the modules which you can try,as there are many such defined on the web.
Therefore a better way to lazy load the cdn from the another domain would be using the javascript loader - script.js
It can be loaded in the following way -
var $script = require("script.js");
$script = ("https://somedomain.com/files/js/js.min.js or https://somedomain.com/files/css/css.min.css",function(){
//.... is ready now
});
This is possible because the script-loader just evaluates the javascript in the global context.
References here
Concerning about the issue of lazy loading the cdn into the angular app
The following library Lab JS is made specifically for this purpose.
It becomes very simple to load and bloack the javascript using this library.
Here is an example to demonstrate
<script src="LAB.js"></script>
<script>
$LAB
.script("/local/init.js").wait(function(){
waitfunction();
});
<script>
OR
You can use the require.js
Here is an example to load the jquery
require.config({
paths: {
"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min"
},
waitSeconds: 40
});
You should also consider the following paragraph from this article.
Loading third party scripts async is key for having high performance web pages, but those scripts still block onload. Take the time to analyze your web performance data and understand if and how those not-so-important content/widgets/ads/tracking codes impact page load times.
I'm developing in DNN 8.0 with its new SPA framework.
I'm using angularjs instead of the defaulted KnockOut.
When I put module setup code in view.html, it works fine. But it doesn't work if I try to put the code in a different file, say app.js. Anyone has seen this before?
A snap shot of the view.html that works looks like this:
[JavaScript:{ jsname: "JQuery" }]
[JavaScript:{ path: "~/Resources/Shared/scripts/dnn.jquery.js"}]
[JavaScript:{ path: "~/DesktopModules/DNNSPA/Scripts/angular.js"}]
[JavaScript:{ path: "~/DesktopModules/MyApp/Scripts/angular-route.js"}]
[JavaScript:{ path: "~/DesktopModules/MyApp/ngApp/app.js"}]
[JavaScript:{ path: "~/DesktopModules/MyApp/ngApp/ngControllers/FirstController.js"}]
[CSS:{ path: "~/DesktopModules/MyApp/CSS/bootstrap.min.css"}]
<script type="text/javascript">
var d = new Date();
var moduleId = parseInt("[ModuleContext:ModuleId]");
var portalId = parseInt("[ModuleContext:PortalId]");
var sf = $.ServicesFramework(moduleId);
var moduleName = "MyApp";
if ("[ModuleContext:EditMode]" === 'True') {
var editMode = true;
}
console.log(editMode);
var currentDate = d;
var app = angular
.module('dnnapp', [
'ngRoute'
])
.config(
function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/DesktopModules/MyApp/partials/firstView.html',
controller: 'firstController'
});
});
app.controller('firstController', function ($scope, $http) {
// controller code
});
</script>
<div class="module-wrap" ng-view>
</div>
All setup code is in view.html.
But if I move the module definition to app.js and controller definition to FirstController.js, it doesn't work.
I've seen others make it work in different files, what am I doing wrong here?
The SPA tokens, ie: [ModuleContext:ModuleId] will not get replaced in your .js file. Therefore you need to do some setup work for your angular module on the page and move all the rest to a js file. Here is one technique:
On your View.html, define an html element for your angular app with an ng-init() method:
<div id='dnnuclear-item-[ModuleContext:ModuleId]' ng-controller="ItemController"
ng-init="init([ModuleContext:ModuleId],'[ModuleContext:ModuleName]','[ModuleContext:EditMode]')">
...
</div>
Also on your View.html, bootstrap your angular app:
<script type="text/javascript">
angular.element(document).ready(function () {
var moduleContainer = document.getElementById('dnnuclear-item-[ModuleContext:ModuleId]');
angular.bootstrap(moduleContainer, ["dnnuclear.ItemApp"]);
});
</script>
Then in your .js file, define the angular module and controller with the init method implementation:
var dnnuclear = dnnuclear || {};
dnnuclear.ItemApp = angular.module("dnnuclear.ItemApp", ['ngDialog']);
dnnuclear.ItemApp.controller("ItemController", function ($scope, $window, $log, ngDialog, dnnServiceClient) {
...
$scope.init = function (moduleId, moduleName, editable) {
$scope.ModuleId = moduleId;
$scope.EditMode = editable;
dnnServiceClient.init(moduleId, moduleName);
$scope.getAll();
}
}
If you need to pass more information to the module than a few variables, I would recommend changing this approach. I have more on this in my DNNHero.com tutorial, Advanced Angular Concepts.
You should try the AngularDNN module. It will probably save your time. It can be found here:
http://store.dnnsoftware.com/home/product-details/angulardnn
I'm trying to use the angular ui router with storm path for angular, but I keep getting an unknown provider error. My code is as follows,
var angular = require("angular");
// app.js
var app = angular.module('app', [require('angular-ui-router'), require("stormpath-sdk-angularjs")]);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'partials/home.html'
})
.state('about', {
url: '/about',
templateUrl: 'partials/about.html'
});
})
.run(function($stormpath){
$stormpath.uiRouter({
loginState: 'login',
defaultPostLoginState: 'home'
});
});
And here is the error page,Error: $injector:unpr
Unknown Provider
This was a bug stormpath-sdk-angularjs and has been fixed in version 0.8.2.
To get it to work with browserify, please add these lines to your package.json:
"browser": {
"stormpath": "./node_modules/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.js",
"stormpath.templates": "./node_modules/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.tpls.js"
}
And then require it like:
var angular = require("angular");
var app = angular.module('app', [
require('angular-ui-router'),
require('stormpath'),
require('stormpath.templates')
]);
Stormpath are using the wrong module name in their module.exports (I've raised a bug here ~ https://github.com/stormpath/stormpath-sdk-angularjs/issues/80).
For now, you can do this
var angular = require("angular");
require('stormpath-sdk-angularjs');
// app.js
var app = angular.module('app', [
require('angular-ui-router'), // this one is fine
'stormpath',
'stormpath.templates'
]);
Generally you do not use the require() in the angular dependency list in this way. Rather you need:
var app = angular.module('app', ['ui-router','stormpath']);
Make sure that both libraries are properly included.
The previous answer is likely part of the solution. Perhaps you are using a tool to compile your application such as WebPack? That information would be useful. Please note that the Stormpath Angular SDK provides two modules in the Angular namespace, stormpath and stormpath.templates. If using browserify, you may need to use require('dist/stormpath-sdk-angularjs.js')
P.S. I work at Stormpath, please feel free to reach us via support#stormpath.com if you would like to privately share your code with us. Thanks!
As it turns out the stormpath sdk injects itself into angular. The solution is to load the library after angular.
var angular = require("angular");
var stormpath = require("stormpath-sdk-angularjs");
var app = angular.module('app', [require('angular-ui-router'), "stormpath", "stormpath.templates"]);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
//States Here
})
.run(function($stormpath){
$stormpath.uiRouter({
loginState: 'login',
defaultPostLoginState: 'home'
});
});
I have an Angular-Meteor application working. I would like to package Angular templates and associated controller into a Meteor package, and inject these templates into my main application by adding that package.
What is best approach?
Update 2015-08-26 - I figured out how to add a template, documented below. But how to have a Meteor package inject the template's Angular controller into the base application?
A key tie-in is Angular UI-router.
I have a base application that includes my package named packageprefix:packagename. Inside this package I have my code in the root of the package folder:
myPackagedPage.ng.html - the Angular HTML template
myPackagedPage.js - the associated Angular controller
From my main application, I tried creating a route to my Angular template like so:
angular.module('parentModule',[
'angular-meteor',
'ui.router',
'angularify.semantic.sidebar'
])
.config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider){
console.log("app.js config!");
$locationProvider.html5Mode(true);
$stateProvider
.state('home', {
url: '/',
templateUrl: 'client/views/home/home.ng.html',
controller: 'HomeCtrl'
})
.state('myPackagedPage', {
url: '/myPackagedPage',
templateUrl: 'packageprefix_packagename/myPackagedPage.ng.html',
controller: 'MyPackagedPageCtrl'
})
;
$urlRouterProvider.otherwise('/');
}])
The application successfully finds the myPackagedPage.ng.html file and renders it. But how to add the controller?
I tried adding this in my package but the controller functions does not get called.
console.log("myPackagedPage.js loaded");
angular.module('parentModule')
.controller('MyPackagedPageCtrl', ['$scope',
function($scope){
console.log("MyPackagedPageCtrl");
}])
;
I get an error:
Argument 'MyPackagedPageCtrl' is not a function, got undefined
I have this working now. Here is the approach that works for me, to inject an Angular Controller + template in a Meteor package, into the containing application.
In my package.js, I have this
Package.onUse(function(api) {
api.versionsFrom('1.1.0.3');
api.use('angular:angular#1.4.4', 'client');
api.use("urigo:angular#0.9.3", 'client');
api.use("session#1.1.0", 'client');
//api.use('angularui:angular-ui-router#0.2.15', 'client');
api.addFiles('interests.js', 'client');
api.addFiles('interests.ng.html', 'client');
api.export("InterestsCtrl", "client")
});
Note you must export your controller, so that the parent application may access it.
In my package, called ramshackle:bigd-interests, I have these files at the root level: package.js, interests.ng.html, and interests.js. interests.js injects the Angular controller, the Anguilar UI-router route to the template, and a sidebar link into the parent application. It accomplishes this by using the Meteor Session. I played with other means of doing this but Session was the only thing that worked. Just be careful to properly scope your session variable names.
//add controllers
var controllers = Session.get("BIGD.controllers");
if (!controllers) controllers = {};
var interestsCtrlSpec = "'$scope', InterestsCtrl";
InterestsCtrl = function($scope){
console.log("InterestsCtrl running");
};
controllers.InterestsCtrl = interestsCtrlSpec;
Session.set("BIGD.controllers", controllers);
//add routes
var routes = Session.get("BIGD.routes");
if (!routes) routes = {};
routes.interests = {
url: '/interests',
templateUrl: 'ramshackle_bigd-interests_interests.ng.html',
controller: 'InterestsCtrl'
};
Session.set("BIGD.routes", routes);
//add sidebar links
//the key determines sorting order
var sidebar = Session.get("BIGD.sidebar");
if (!sidebar) sidebar = {};
sidebar["interests"] = {
url: '/interests',
templateUrl: 'ramshackle_bigd-interests_interests.ng.html',
controller: 'InterestsCtrl',
rank: 5
};
Session.set("BIGD.sidebar", sidebar);
var interestsItem = {label: 'Interests', link: '/interests', icon: "rocket"};
In my parent application's app.js , I dynamically loaded the controllers and routes from the session like this:
angular.module('bigdam',[
'angular-meteor',
'ui.router',
'angularify.semantic.sidebar',
'nvd3',
'leaflet-directive',
'ui.router.history'
])
.config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider){
//console.log("app.js config!");
$locationProvider.html5Mode(true);
//add a static state
$stateProvider
.state('home', {
url: '/',
templateUrl: 'client/views/home/home.ng.html',
controller: 'HomeCtrl'
});
//add the dynamic routes/states from other Meteor packages
for (var stateId in routes) {
var route = routes[stateId];
$stateProvider
.state(stateId, route);
}
$urlRouterProvider.otherwise('/');
}])
;
//Declare the controllers from plugins
for (var controllerId in controllers) {
var controllerSpec = controllers[controllerId];
var controllerSpecArray = eval("[" + controllerSpec + "]")
angular.module('bigdam').controller(controllerId, controllerSpecArray);
}
So now, when I create a new Meteor package, and follow the convention described above, its controllers, routes, and sidebar links get loaded into the main application.