Make angular Manually go to compile phase - javascript

I'm using ocLazyLoad to load my modules on demand in Angular. These modules are totally different and we should check using the server which module should we load. Before Using ocLazyLoad I was loading all concatenated js files of these separate modules in my main View. So all of them we're loading.
Now as it's obvious I'm loading these files on demand, which mean it should read data from the server and see which modules should be loaded and load a megabyte File and most importantly load it before angular begins to compile the View.
I was using ocLazyLoad's promise to $compile the view (body) but since it was being done twice or even more sometimes my directives weren't working.
So I think I have two options:
Make angular manually compile the view (which I searched a lot and I couldn't find how!!) after the modules are injected and loaded by ocLazyLoad!
Read the list of needed modules from the server and use LazyLoad in the maybe run phase of the app or even before angular.bootstrap. (I've done this already but since the $http request is being done async It works sometimes and it loads before angular compile and sometimes it doesn't)
I would appreciate it if you could help me with this.
spa.run(['$rootScope', '$location', '$route', '$localStore', '$templateCache', 'Analytics', 'preflightValue', '$ocLazyLoad', '$http',
'$compile', function($rootScope, $location, $route, $localStore, $templateCache, Analytics, preflightValue, $ocLazyLoad, $http, $compile ) {
$rootScope.$on('cfpLoadingBar:completed', function(event, args) {
angular.element($('body')).addClass('cfp-done');
});
$http({
method: 'POST',
url: url,
data: {
route: "/dashboard"
},
headers: {
// My Headers
}
}).success(function (data, status, header, config) {
var currentModules = $ocLazyLoad.getModules();
for (var i = 0; i < data.data.cloudwares.length; i++) {
var moduleName = data.data.cloudwares[i];
if (currentModules.indexOf(moduleName) === -1 && moduleName !== 'bot-manager') {
preflightValue.addModule(moduleName);
}
}
$ocLazyLoad.load(preflightValue.modulesList()).then(function () {
preflightValue.emptyList();
});
});
}]);
// Update
Please pay attention that we're not using ui-router or ngRouter. We're getting the state of our route from the server each time using $resource.

In your config file try to state the route with lazyload event
app
.config(function ($stateProvider, $urlRouterProvider,ParseProvider){
.state ('home', {
url: '/home',
// templateUrl: 'views/home.html',
templateUrl: 'views/home.html',
resolve: {
loadPlugin: function($ocLazyLoad) {
return $ocLazyLoad.load ([
{
name: 'css',
insertBefore: '#app-level',
files: [
'vendors/bower_components/fullcalendar/dist/fullcalendar.min.css',
],
},
{
name: 'vendors',
insertBefore: '#app-level-js',
files: [
'vendors/sparklines/jquery.sparkline.min.js',
'vendors/bower_components/jquery.easy-pie-chart/dist/jquery.easypiechart.min.js',
'vendors/bower_components/simpleWeather/jquery.simpleWeather.min.js'
]
}
])
}
}
})
})
from this you can load any scripts to your view.

I Actually Solved this Issue by asking another question! All I had to do was to return two promises!
Find the solution Here: Use a $routeProvider resolve function inside another one

Related

How to force a browser to reload angular template file and not cache it?

When loading a javascript file I can force the browser to not use the cache by adding a version when loading the file e.g.
<script src="~/angular/myapp/app.js?version=123"></script>
From inside my angular app I am doing this:
$routeProvider.when("/", {
controller: "userController",
controllerAs: "vm",
templateUrl: "Path/to/Template/Index.html"
});
How can I make sure that any changes I made to the Index.html won't be cached? Or this isn't an issue for some reason?
angular 1.x
You could do the same for your Index.html file. Simply append a "cache buster" query string as you did to your js file. There are a few techniques to do this, but a simple Date.now() timestamp should demonstrate the goal
...
$routeProvider.when('/', {
controller: 'userController',
controllerAs: 'vm',
templateUrl: `Path/to/Template/Index.html?t=${Date.now()}`
});
If your app grows in complexity and you wish to prevent caching of templates altogether, you can achieve this with some middleware...
angular.module('preventTemplateCache').factory('preventTemplateCache', function($injector) {
return {
'request': function(config) {
if (config.url.indexOf('views') !== -1) {
config.url = `${config.url}?t=${Date.now()}`
}
return config;
}
}
}).config(function($httpProvider) {
$httpProvider.interceptors.push('preventTemplateCache');
});
The above example assumes a directory of views for your templates.
Finally, as a comment pointed out, if you are simply wishing to prevent caching for local development, you can toggle settings to disable cached resources through your browsers dev tools.

External view html files in Angularjs Route

Please advice how to include(use) commonly used and shared between few projects html files.
so html files from external server needs to be included in Angularjs router.
Here is a short example of what i have and what i am trying to solve.
Now .html is in my project folder:
.state('chatbase', {
url: '/cn={cn}',
onEnter: function ($stateParams, ParamsShareService) {
ParamsShareService.updateCnValue($stateParams.cn);
},
views: {
'content#': {
templateUrl: 'views/chat_wv1.html',
controller: 'ChatController'
}
}
})
And i am trying to get them work like this.So i can share the structure for few projects.
.state('chatbase', {
url: '/cn={cn}',
onEnter: function ($stateParams, ParamsShareService) {
ParamsShareService.updateCnValue($stateParams.cn);
},
views: {
'content#': {
templateUrl: 'https://my-website/views/chat_wv1.html',
controller: 'ChatController'
}
}
})
I think the way you implemented it will not work.
templateUrl support explicit path to your project or String.
HTML is a static file with static content. However calling file from HTTP means get file content by using HTTP protocol - different flow and templateUrl doesn't support this way.
Further, Angular state is loaded before any controller and I believe templateUrl: 'views/chat_wv1.html', is what we have today.
You can try this approach (but its a bit complicated):
1) you can load some teplate.html
views: {
'content#': {
templateUrl: 'views/teplate.html',
controller: 'ChatController'
}
}
2) The teplate.html will be bind to some Controller that will load HTML content from server and you can use $compile + ng-include to achieve what you look for

Lazy loading Angular modules with Webpack

I'm trying to get lazy-loaded Angular modules working with Webpack, but I'm having some difficulties. Webpack appears to generate the split point correctly, because I see a 1.bundle.js getting created that contains the code for the child app, but I don't see any request for 1.bundle.js when I load the page, and the child app doesn't initialize. The console.log never seems to fire, and it doesn't even appear to get to the point where $oclazyload would initialize the module.
There are a few points where I am confused.
1) Will webpack make the request to the server, or do I have to load the second bundle manually? (I've tried both, and neither works)
2) If I do need to load the bundles manually, in what order should they be loaded?
3) The third argument to require.ensure supposedly lets you control the name of the bundle, but the bundle is named 1.bundle.js no matter what string I pass.
4) Why can't I step through the code inside the require.ensure block in the debugger? When I do so I end up looking at this in the Chrome source view:
undefined
/** WEBPACK FOOTER **
**
**/
(Code Below)
Main entry point code:
'use strict';
import angular from 'angular';
import 'angular-ui-router';
import 'oclazyload';
angular.module('parentApp', [
'ui.router',
])
.config(['$urlRouterProvider', '$locationProvider', ($urlRouterProvider, $locationProvider) => {
$urlRouterProvider
.otherwise('/');
$locationProvider.html5Mode(true);
}])
.config(['$stateProvider', ($stateProvider) => {
$stateProvider
.state('child-app', {
url: '/child-app',
template: '<child-app></child-app>',
resolve: {
loadAppModule: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require.ensure(['./child-app/app.js'], (require) => {
let module = require('./child-app/app.js');
console.log(module);
$oclazyload.load({name: 'childApp'});
resolve(module.controller);
});
})
}
},
controller: function() {
}
})
}]);
Child app:
'use strict';
import childAppTemplateURL from '../templates/child-app.html';
import childAppController from './controllers/childAppController';
export default angular.module('parentApp.childApp', [])
.component('applicationListApp', {
templateUrl: childAppTemplateURL,
controller: childAppController
});
The problem was unrelated to the require.ensure implementation. It was caused by some weirdness in the way ocLazyLoad is packaged (https://github.com/ocombe/ocLazyLoad/issues/179). The fix in my case was simple, I just added 'oc.lazyLoad' to the module dependencies.
angular.module('parentApp', [
'ui.router',
'oc.lazyLoad'
])
To answer two of my own questions, Webpack does indeed make a request to the server for the bundle, and you do not have to manually load the bundle. One gotcha that really confused me: the resolve block will fail silently if it contains a promise that won't resolve. In my case $ocLazyLoad.load() was failing, but there was no indication of the failure. The only clue was that the state provider wasn't adding the <child-app></child-app> markup to the DOM, which meant that it was actually initializing the state.

Lazy loading Angular directives in ui-router as Webpack chunks

I am trying to lazy load an Angular directive as a webpack chunk.
Here is my current config attempt at using ocLazyLoad:
// Basic Config
function routingBase( $urlRouterProvider, $locationProvider, $stateProvider ) {
$locationProvider.html5Mode(true);
$stateProvider
.state('home', {
url: '/home',
template: '<app-main></app-main>',
resolve: {
load: ( $q, $ocLazyLoad ) => {
let deferred = $q.defer();
require.ensure([], (require) => {
// Load entire module
let module = require('../modules/main');
$ocLazyLoad.load({
name: module.name
});
deferred.resolve(module);
}, 'app-main');
return deferred.promise;
}
}
})
}
This goes in myModule.config(routingBase);.
../modules/main is just an angular module that exports a directive (e.g. export default angular.module('main',[]).directive('appMain', appMainFn);.
Any tips? What I am getting is that the <app-main></app-main> is correctly added to the document, and that the chunk is correctly loaded as module. But it is not replaced (it stays as <app-main></app-main>).
Would you recommend a different method for lazy loading chunks (maybe using $compileProvider)? I would like the cleanest possible way.
Thank you very much for your help.
I was able to get this working in my current project. Just change the following line and see it works. You need to add default as well since you are exporting angular module as default. Cheers!
$ocLazyLoad.load({
name: module.default.name
});

Angular controller not loading using OcLazyLoad and ngRoute

I have an app that which has a load of scripts loading initially and the list is growing as development goes on. I want to lazy load scripts which contain controllers as and when needed. I am using OcLazyLoad along with ngRoute for the routing option (i did try ui-route which actually had the same end result but was causing other app issues). The lazy load and routing is working fine, scripts and views are only loaded when needed, but the issue is the controller is not being loaded (Argument 'caseReviewController' is not) so it's as though the controller does not exist.
Here is a simple version of what I have in my app.js file...
var app = angular.module('dashboard', ['oc.lazyLoad', 'ngRoute', 'LocalStorageModule']);
app.config(function ($ocLazyLoadProvider, $routeProvider, localStorageServiceProvider) {
$ocLazyLoadProvider.config({
loadedModules: ['dashboard'], modules: [
{
name: 'caseReview',
files: ['js/controllers/case-review.js']
}
]
});
$routeProvider
//other routes here...
.when('/case-review', {
templateUrl: 'views/case-review.html',
controller: 'caseReviewController',
resolve: {
loadModule: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('caseReview');
}]
}
})
});
In the seperate case-review.js file I have a simple controller
app.controller('caseReviewController', function($scope, localStorageService, $route){
//do stuff
});
This controller is not being found or executed but the view and js file are being lazy loaded as expected. Any help would be great.
Thanks.
In your separate case-review.js, you must get the reference of app.
angular.module('dashboard').controller('caseReviewController', function($scope, localStorageService, $route){
//do stuff
});
As you've mentioned it's in separate file, it may not know about the app variable. It's better to get the reference of the angular module in the separate file.
This must solve your issue.

Categories