Angular JS: Load CSS and JS files dynamically - angularjs

I am in the middle of developing a web app. I am using AngularJS for loading all the files dynamically into the UI.
I have an index.html file into which all the files will be loaded dynamically on-click or on-load.
//index.html
<signin button> <signup button> // etc.,
//on-clicking signin button a SignIn-page will load in the below div
<div id="bodyview"></div>
// end of index.html
Now my sign-in page looks somewhat like the below structure
/*a div where my accordion menu will load when the
*below submit button is clicked*/
<div id="menu"></div>
//other sign-in-form stuff will follow on...
//submit button at the end
<submit button> //only on clicking the submit button the menu will be loaded
Now my problem is, though I'm able to load the accordion menu.html file, I'm not able to load the css and js files it is dependent on. I have researched on stackoverflow but none worked for me.
Can anybody please help in determining a way for loading the css and js dependencies using AngularJS

Just write a service to add CSS and JS files to the <head>
Here is a example service which is used to dynamically load CSS files.You can modify it easily to load JS files.
https://github.com/Yappli/angular-css-injector

Currently I use angular-css: https://github.com/door3/angular-css
Imho, it's one of the best and most flexible solutions at the moment.

Instead of going by AngularJS way, i tried to load the files using JQuery. It worked for me.
You can check this link for reference

I used jquery to do the hardwork like this
/** resolve will come inside your route .when() function **/
resolve: {
theme: function ($route, $q) {
changeCss($route, $q);
}
}
/** This will come just outside your route .when() function, make sure the following function shall be in scope of the route provider **/
var changeCss = function ($route, $q) {
var defer = $q.defer();
// Change the CSS as per the param received
if ($route.current.params.css != undefined) {
if ($route.current.params.css === ‘dark’) {
loadCSS(“assets / css / dark.css”);
defer.resolve();
}
if ($route.current.params.css === ‘light’) {
loadCSS(“assets / css / light.css”);
defer.resolve();
} else {
defer.resolve();
}
}
return defer.promise;
}
var loadCSS = function (href) {
var cssLink = $(“ < link rel = ’stylesheet’ type = ’text / css’ href = ’”+href + “‘ > ”);
$(“head”).append(cssLink);
};
I have used Promise because this will make sure to load the css before it shows/load the angularjs route/page.

app.controller('MyCtrl', function($scope,$compile) {
$("#my").append( $compile("<script src='my.js'>")($scope) );
});

Related

AngularJs ui-router reload template

I have a angularjs project that's using ui-router for routing.
I am using $state.reload() to reload the current state and it works just fine except that in my development system i want the $state.reload() to also reload the html template to reflect the new changes without a full page reload.
Is there a hack or option to do this ?
Update :
Chris T's solution almost worked, but i have templateFactoryDecorator witch adds a cache buster to the template url.
function configureTemplateFactory($provide) {
// Set a suffix outside the decorator function
var cacheBuster = Date.now().toString();
function templateFactoryDecorator($delegate) {
var fromUrl = angular.bind($delegate, $delegate.fromUrl);
$delegate.fromUrl = function (url, params) {
if (url !== null && angular.isDefined(url) && angular.isString(url)) {
url += (url.indexOf("?") === -1 ? "?" : "&");
url += "v=" + cacheBuster;
}
return fromUrl(url, params);
};
return $delegate;
}
$provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}
so
$templateCache.remove($state.current.templateUrl);
didn't work and i had to use
$templateCache.removeAll();
Its not ideal but for development environment its ok.
Internally, UI-Router leverages the $templateCache service to avoid re-fetching templates. Before calling $state.reload(), clear out the template you want to refetch from the server.
Assuming you want to do this from a controller:
function MyController($scope, $templateCache, $state) {
$scope.reload = function() {
$templateCache.remove("/path/to/template.html");
$state.reload();
}
}
Docs:
$templateCache
$cacheFactory
On a side note, I find it odd that you would want to refetch the template from the server.
I may have missed your point but When you use $state.reload() it reloads the state that means all the partials in side that template and the controllers in side that controller scope. Thus the state is reloaded not the full page.
So I see no errors in your side unless you want to do other staff ..
And if you are dynamically generating the DOM, It will do it for you .

Using jquery mobile external page with a angular js controller

Hello im working on a web app project, and we are using jquery mobile for the pages ui and angular for mvc reasons,
Im having a problem using my external pages ( pages that ive load to my index.html), they dont recognize my controllers (only works the controllers that ive put in the index.html)
ill some of my code here to explain my problem
if ive put some angular values in my external page (previews declaration of the controller in my
<div data-role="page" id="ResEjecSuc" class=".paginas"
data-dom-cache="true" ng-controlles="categController" >
)
<span ng-class="sucursal.TIT_CATEGORIZACION">
{{sucursal.TIT_REALIZADA}}</span>
my app only shows: {{sucursal.TIT_REALIZADA}}
my controller init code :
app = angular.module('nevadaProt', [])
app.controller('categController', controlerCateg)
controlerCateg = function($scope, $locale) {
var sucursal = {
TIT_CATEGORIZACION:4,
TIT_REALIZADA:12
}
how ive load and after that transition to my html page:
Load:
$.mobile.pageContainer.pagecontainer("load",
"pages/RappidApps2/ResumenEjecZona.html", {});
transition:
$.mobile.pageContainer.pagecontainer("change", "#ResEjecSuc", {
transition : "pop",
reverse : false
});
how can i make work angular controllers and external jquery mobile pages?
Once you are using Angular, you may create a directive.
app.directive('externalHtml', function(){
return {
restrict : 'E'
,replace : true
,templateUrl : 'pages/RappidApps2/ResumenEjecZona.html'
};
});
then, you html should be something like:
<body>
<div data-role="content">
<external-html/>
</div>
</body>
It always works for me.

how to call a controller in ionic?

In my ionic blank app, i have two html file index.html and category.html.
i write the controller for index.html in app.js like
.controller('AppCtrl',function($scope){
$scope.menu = function() {
console.log('yesytest');
window.location = "category.html";
};
})
this is working fine and after reaching the category page i create another controller in app.js
controller('categoryCtrl',function($scope){
console.log('ffffffffff');
$scope.beauty = function() {
console.log('yesytest');
window.location = "categorydetails.html";
};
});
i add a ng-click function on a button inside category.html but when i click on that button it is not calling the controller?
You can define your controller either on :
- defining it on your ui router state
.state('camera',{
url:"/camera",
cache: false,
controller:"CameraCtrl",
templateUrl:'app/views/loading/index.html'
})
Or by defining it into tour template category.html
<div ng-controller="categoryCtrl"> .... </div>
This is standard AngularJS feature, nothing special with ionic
If you use this :
.state('category',{
url:"/category",
controller:"categoryCtrl",
templateUrl:'templates/category.html'
})
You can use ui-sref="stateId" to do redirection
Example:
<a ui-sref="category"></a>
..Hi Kindly route your controller just define them..This might help.. --> http://learn.ionicframework.com/formulas/navigation-and-routing-part-1/ ^_^
//app.js
.state('category',{
url:"/category",
controller:"categoryCtrl",
templateUrl:'templates/category.html'
})
//index.html
<a ng-href="#/category"></a>

How can I start fetching data from the server as quickly as possible?

How can I start fetching data from the server as quickly as possible with Angular?
Currently, most of my page is populated asynchronously via a directive "fooload" placed at the root element:
<html lang="en" ng-app="myapp" fooload ng-controller="MyAppCtrl">
<head>
/* bunch of CSS, and other resources */
</head>
Which loads data into the scope via an http GET request:
angular.module('myapp.directives').
directive('fooload', function ($http) {
return {
link: function (scope, elm, attrs) {
$http.get('/foo').success(function (data) {
scope.foo = data;
});
}
};
});
Looking at the network panel, this call is being made in the browser AFTER the requests for the resources referenced in head. How can I make the call to load /foo data as quickly as possible on page load (if possible, even before loading angular itself)?
This is not really related to Angular, obviously Angular cannot start loading files before Angular has loaded itself. But if the resource (eg /foo) is cacheable by the browser you could add it to a manifest file: http://www.html5rocks.com/en/tutorials/appcache/beginner/
I solved this by:
a) fetching the data even before angular loads and storing it in a global variable (I hate using a global variable, but I couldn't think of another way.)
b) manually bootstrapping angular upon load of this data (my app doesn't work at all without the data)
var $data;
var ajax_transport = new XMLHttpRequest();
// Callback for AJAX call
function responseProcess() {
if (ajax_transport.readyState !== 4) {
return;
}
if (ajax_transport.responseText) {
$data = JSON.parse(ajax_transport.responseText);
angular.bootstrap(document, ['myApp']);
});
}
}
// Sending request
ajax_transport.open("GET", "/mydata", true);
ajax_transport.onreadystatechange = responseProcess;
ajax_transport.send();
Note: it's important to remove the tag ng-app="myapp" in your template to avoid automatic bootstrapping.
c) Using the data in my angular app:
scope.setupSomething($data);
d) Also, to ensure that this data call begins before any other resource load, I started using a resource loader. I liked HeadJs (http://headjs.com/) the most, but the angular folks seem to like script.js (https://github.com/angular/angular-phonecat/blob/master/app/index-async.html)
Criticism or improvements welcome.
Start by creating a new service that gets the resource and then bootstraps the document for angular upon success callback from the server.
angular.element(document).ready(function() {
calllService(function () {
angular.bootstrap(document);
});
});
https://stackoverflow.com/a/12657669/1885896

Single page application - load js file dynamically based on partial view

I've just started learning Angular and following the tutorial here - http://docs.angularjs.org/tutorial/step_00
I'm downloaded the seed example from GitHub and it works great. I have a question though - if a partial view requires an external js file to be referenced, does it need to be added to the index.html file at the beginning? I want the app to be as lean as possible and only want to include the js references that are required for the present view. Is it possible to load the js files dynamically based on a view?
This just worked for me. Figured I would post it for anybody else seeking the lightest-weight solution.
I have a top-level controller on the page's html tag, and a secondary controller for each partial view.
In the top-level controller I defined the following function…
$scope.loadScript = function(url, type, charset) {
if (type===undefined) type = 'text/javascript';
if (url) {
var script = document.querySelector("script[src*='"+url+"']");
if (!script) {
var heads = document.getElementsByTagName("head");
if (heads && heads.length) {
var head = heads[0];
if (head) {
script = document.createElement('script');
script.setAttribute('src', url);
script.setAttribute('type', type);
if (charset) script.setAttribute('charset', charset);
head.appendChild(script);
}
}
}
return script;
}
};
So in the secondary controllers I can load the needed scripts with a call like the following…
$scope.$parent.loadScript('lib/ace/ace.js', 'text/javascript', 'utf-8');
There's a slight delay before the objects contained in the external script are available, so you'll need to verify their existence before attempting to use them.
Hope that saves somebody some time.
I just tried the https://oclazyload.readme.io/. It works out of the box.
bower install oclazyload --save
Load it in your module, and inject the required module in controller:
var myModule = angular.module('myModule', ['oc.lazyLoad'])
.controller('myController', ['$scope', '$ocLazyLoad', '$injector',
function($scope, $ocLazyLoad, $injector) {
$ocLazyLoad.load(
['myExtraModule.js',
'orAnyOtherBowerLibraryCopiedToPublicFolder.js'
])
.then(function() {
// Inject the loaded module
var myExraModule = $injector.get('myExtraModule');
});
}
]);

Resources