Angular-js Include js on each state - javascript

Hi I have created an angular application and I have created separate controller for each
I want to load each controller when the corresponding state has been reached
I don't to want to load all controller at my index.html
My index.html
<!-- UI Elements-->
<link rel="stylesheet" type="text/css" href="common/resources/UI/css/bootstrap.css">
<script src="common/resources/UI/js/bootstrap.js"></script>
<!-- UI Elements-->
<!--Angular Elements-->
<!--Angular js file from google-->
<script src="common/resources/Angular/Angular/angular.js"></script>
<script src="common/resources/Angular/Angular/angular-route.js"></script>
<script src="common/resources/Angular/Angular/angular-ui-router.js"></script>
<script src="common/resources/Angular/Angular/angular-router-styles.js"></script>
<!--Angular js file from google-->
<!--Angular Modules-->
<script src="common/resources/Angular/Module/module.js"></script>
<!--Angular Modules-->
<!--Angular Route Config-->
<script src="common/resources/Angular/Module/Configuration/rootConfig.js"></script>
<!--Angular Route Config-->
<!--Angular Controller-->
<script src="common/resources/Angular/Controller/ControllerImpl/mainControllerImpl.js"></script>
<script src="common/resources/Angular/Controller/controllers.js"></script>
<!--Angular Controller-->
My RootStatefile
I want to load login.js and use controller loginController when state chnages to /login
/*
Summary : Login Page
Description : Used to show the login page of application
Author : Nithin Prasad
*/
.state('/login', {
url: '/',
controller: 'loginController',
templateUrl: 'module/login/login.html',
data: {
css: [
{
href: 'module/login/css/login.css'
}
],
scripts: [
{
href: 'module/login/js/login.js'
}
]
}
})
I don't want to write all controller implementation in one file and i want it to modularized
Please help
my login.js
var loginController = function ($scope, $log) {
$scope.userName = "nithinprasad59#yahoo.com";
$scope.password = "nithin123";
$scope.userEmail = $scope.userName;
}
smartExpenseApp.controller('loginController', loginController);
my login.html
has a reference to loginController
<div class="container" ng-controller="loginController">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="jumbotron">
<h1>Login</h1>
<form class="form-horizontal" name="loginForm">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" required id="inputEmail3" placeholder="Email" name="email" ng-model="userEmail">
</div>
</div>
<div ng-show="loginForm.email.$dirty && loginForm.email.$invalid" class="alert alert-danger" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span ng-show="loginForm.email.$error.required">Email is required.</span>
<span ng-show="loginForm.email.$error.email">Invalid email address.</span>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" required name="password" class="form-control" id="inputPassword3" placeholder="Password" ng-model="password">
</div>
</div>
<div ng-show="loginForm.password.$dirty && loginForm.password.$invalid" class="alert alert-danger" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span ng-show="loginForm.password.$error.required">Password is required.</span>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Sign in</button>
</div>
</div>
Hello ! {{userEmail}} Your password is {{password}}
</div>
</div>
</form>
</div>
</div>
</div>
but i am getting following error
LoginControler not found

You want to load the files only when its needed. Such type of loading is called lazy loading. You can add only the primary js and css files in the html and can load the template html and other js files later on when needed.
You can use oclazyload for this.
first do install the dependancy file using bower or npm.
bower install oclazyload
or
npm install oclazyload
then you need to add the module to your application
var smartExpenseApp = angular.module("smartExpenseApp", ["oc.lazyLoad"]);
You are done with that. now inject the dependancy in your controller file that you are added in the index.html.
smartExpenseApp.controller("MyCtrl",['$ocLazyLoad', function($ocLazyLoad) {
//do something here
//now you need your login controller
$ocLazyLoad.load('login.js');
}]);
You can load a file inside a function, switch cases etc.
for more details refer https://oclazyload.readme.io/docs

You need to include your login.js file in index.html, just as you have included others. This is necessary to include all js files, so that they are loaded in sequence. Otherwise your controller function will not be found by system.
If you don't want to load all files at startup on single page load, then you can use angular lazyloading feature, and $controllerProvider.
http://ify.io/lazy-loading-in-angularjs/

Related

angularTemplatecache + gulp not working correctly

I'm using angularTemplatecache with gulp to put all my HTML in a templates.js file but I keep getting an error and cant seem to get it to work.
Uncaught ReferenceError: module is not defined
This error seems to be originating from templates that have ng-include in them because if I remove them from the templates.js file and load them normally it works. Here is one template that is giving me problems
<div class="box-flight-search" ng-show="showNewFlightSearch">
<flight-search-options fn-flight-search="onFlightSearch"
city-airport-data="citiesAndAirportsData"
airv-data="airvsData"
ptc-data="ptcData"
fare-class-data="fareClassData"></flight-search-options>
</div>
<div class="box-flight-search" ng-show="showLastPnr && showNewFlightSearch">
<ng-include src="'app/dashboard/views/dashboard.last.pnrs.html'" />
</div>
<div class="container-fluid" ng-if="!showNewFlightSearch">
<div class="row">
<!-- ng-hide="showNewFlightSearch" -->
<div class="main-search-wrapper">
<div class="inner animated">
<uib-tabset active="0">
<uib-tab index="0">
<uib-tab-heading class="lead">
<i class="glyphicon glyphicon-plane"></i> {{::resource.fields.Fields.FLIGHT_SEARCH}}
</uib-tab-heading>
<br />
<ng-include src="getTemplate('flightSearch')"></ng-include>
</uib-tab>
</uib-tabset>
</div>
</div>
</div>
<div class="row" ng-show="viewLastPnr">
<ng-include src="'app/dashboard/views/dashboard.last.pnrs.html'"
ng-controller="DashboardLastPnrController"
ng-init="onInit(false)" />
</div>
</div>
The getTemplate function i something like this
$scope.getTemplate = function (template) {
switch (template) {
case "flightSearch":
return $scope.viewsPath + "views/dashboard.search_NXG.html";
case "lastPnr":
return $scope.viewsPath + "views/dashboard.last.pnrs.html";
case "queues":
return $scope.viewsQueues + "views/queues.component.html";
}
};
any ideia on how to resolve this?
EDIT: here is my template.js. the file has more but i just removed for simplicity
angular.module("AppRoot").run(["$templateCache",function($templateCache){
$templateCache.put("footer.html",'html here'),
$templateCache.put("app/dashboard/views/dashboard.last.pnrs.html",'html here),
$templateCache.put("app/dashboard/views/dashboard.retrieve.reservation.html",'html here')}]);
AppRoot is the root module for the application

File Input - Unable to get property 'addEventListener' of undefined or null reference

I have an input file control which I want to use to select a .csv file. I have been trying to add an event listener to the control so that a function 'csvFileSelected' is called when a file is selected.
However, whenever my app tries to add the event listener an error is thrown saying:
0x800a138f - JavaScript runtime error: Unable to get property 'addEventListener' of undefined or null reference
My javascript file looks like:
function bindEvents() {
$(document).ready(function () {
document.getElementById("uploadCSVFile").addEventListener('change', csvFileSelected, false);
});
}
function csvFileSelected()
{
// Get CSV file and store in a hidden field
var csvFile = document.getElementById("uploadCSVFile").files[0];
}
This is my HTML code:
<div class="panel panel-info">
<div class="panel-heading text-center" style="font-weight: bold;">Bulk Invite</div>
<div class="panel-body">
<div class="form-group">
<div class="row" style="text-align: center;">
<div class="col-xs-12 col-md-offset-3 col-md-3" style="font-weight: bold; padding-top: 15px">
Import Users From .CSV File:
</div>
<div class="col-xs-12 col-md-3" style="padding-left: 50px;">
<div id="csvBtn" class="btn btn-default fileUpload" runat="server">
Select File
<input id="uploadCSVFile" class="upload" type="file" accept=".csv" runat="server" />
</div>
</div>
<div class="col-xs-12 col-md-3">
<asp:Label ID="fileName" runat="server" Text=""></asp:Label>
</div>
</div>
</div>
</div>
</div>
On my HTML page I have this script which is placed after the HTML elements:
<script type="text/javascript">
// called at the start of page load
$(document).ready(function () {
bindEvents();
});
</script>
I have tried many various possible solutions for this error however none of them worked for me.
I have made sure the script is placed at the bottom of the HTML page as well as having it encased $(document).ready so the listener shouldn't get added until the HTML has loaded, but this does not work.
I have also tried using:
window.onload = function(){
document.addEventListener('DOMContentLoaded', function () {
I have also used the JQuery statement for adding an event listener and I have tried using a different element, both still throw the same error.
It seems to me as though the functions are getting called even before the document/page is ready.
Any help would be greatly appreciated.
The issue is that your telling the server to do the file selection input at the server level, not the client level.
What this means is that the server will actually generate the element server-side, and consider it to only exist there.
By removing the runat="server", you will be able to interface with that element using Javascript (which is client side)
I also added the jQuery headers to the top of the HTML and put it into the Code Snippet for you (by clicking on the little icon that looks like < > on top of a piece of paper).
What needs to be changed is:
<input id="uploadCSVFile" class="upload" type="file" accept=".csv"/>
and also add this:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
And it should work fine.
function bindEvents() {
$(document).ready(function() {
document.getElementById("uploadCSVFile").addEventListener('change', csvFileSelected, false);
});
}
function csvFileSelected() {
// Get CSV file and store in a hidden field
var csvFile = document.getElementById("uploadCSVFile").files[0];
console.log(csvFile);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="panel panel-info">
<div class="panel-heading text-center" style="font-weight: bold;">Bulk Invite</div>
<div class="panel-body">
<div class="form-group">
<div class="row" style="text-align: center;">
<div class="col-xs-12 col-md-offset-3 col-md-3" style="font-weight: bold; padding-top: 15px">
Import Users From .CSV File:
</div>
<div class="col-xs-12 col-md-3" style="padding-left: 50px;">
<div id="csvBtn" class="btn btn-default fileUpload" runat="server">
Select File
<input id="uploadCSVFile" class="upload" type="file" accept=".csv"/>
</div>
</div>
<div class="col-xs-12 col-md-3">
<asp:Label ID="fileName" runat="server" Text=""></asp:Label>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
// called at the start of page load
$(document).ready(function() {
bindEvents();
});
</script>

AngularJS Function gets called many times?

I have a very simple js file for my angular app.
angular.module('Account', ['firebase'])
.value('fbURL', 'https://myURL.firebaseio.com/')
.service('fbRef', function(fbURL) {
return new Firebase(fbURL)
})
.controller('Authorization', function($scope, $firebase, $firebaseObject, fbRef){
var auth = this;
auth.loginEnabled = function() {
alert('false');
return false;
}
auth.loginEmail = function() {
}
});
The auth.loginEnabled function gets called many times (the alert appears many times) when my html loads. Why is this?
In my html
ng-app is declared in my html tag as ng-app="Account"
ng-controller is delcared in my <div class="container"> that wraps an if for angular
ng-if is declared twice, once for a true return and once for a false.
In short, here is my html code: (all your missing is the ng-app code described above)
<div class="container login-container" ng-controller="Authorization as auth">
<div class="row">
<div class="col-sm-12">
<form class="" action="" method="">
<div class="card-container manual-flip">
<div class="card">
<div class="front">
<div class="cover">
<img src="<?php echo $base; ?>assets/img/rotating_card_thumb2.png"/>
</div>
<div class="content" ng-if="auth.loginEnabled()">
<div class="main">
<h3 class="name">Login</h3>
<p class="profession">My Account</p>
<div class="form-group">
<input type="email" ng-model="email" class="form-control" placeholder="E-mail Address">
</div>
<div class="form-group">
<input type="password" ng-model="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="footer">
<button type="submit" class="btn btn-block btn-primary">Login <i class="fa fa-arrow-right"></i></button>
</div>
</div>
<div class="content" ng-if="!auth.loginEnabled()">
<div class="main">
<h3 class="name">Login</h3>
<p class="profession">Temporarily Unavailable</p>
<p class="text-center">We are currently updating our system for a better user experience! Please check back within a few hours.</p>
</div>
<div class="footer">
<i class="fa fa-reply"></i> Return Home
</div>
</div>
<div class="back">
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
I'm wanting to disable the login function all together at certain times, not see if the user is already logged in.
As Orel mentioned, the cause for the repeated alert is simply that your loginEnabled function is called upon every digest cycle. Without going into too much detail, Angular is frequently reevaluating those functions and values bound to the scope to ensure your UI is representing your data accurately.
Thus, it would be preferable to assign the loginEnabled value to a Boolean and query that within the scope:
auth.loginEnabled = false;
$rootScope.$on('myAuthenticationEvent', function () {
auth.loginEnabled = true;
});
The usage of the $rootScope isn't necessary, but serves to demonstrate that some other function in your controller (perhaps a Firebase observer) could be responsible for updating your auth.loginEnabled value. Hope this helps!
The reason is that your controller is called twice, may be because of this
ng-controller="Authorization as auth is mentioned in your view and also while configuring your route you might also include controller there too. like below
url: '/your url',
config: {
templateUrl: 'url',
controllerUrl: 'url',
controller:'Authorization'
}
If that is the case then, change your code to
url: '/your url',
config: {
templateUrl: 'url',
controllerUrl: 'url',
}

jQuery find id after loading

Here is my structure:
Person.html
...
<script src="../../js/site.js"></script>
...
<a id="findPersonById" href="javascript:void(0);" class="btn btn-primary">
Find person by id</a>
...
<div id="person-result">results div</div>
Site.js
$(document).ready(function () {
privateFunction();
});
...
$('#findPersonById').click(function () {
$("#person-result").load('/person/find #inside-container');
});
...
/person/find
<script src="../../js/site.js"></script>
...
<div class="container">
<div id="inside-container">
<br/>
<form id="personFindByIdForm">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">PERSON'S ID</span>
<input type="text" class="form-control" name="id"/>
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Find</button>
</span>
</div>
</div>
</form>
<div id="find-result">res-div</div>
</div>
So, first of all I'm finding #findPersonById and loading /person/find #inside-container in the #person-result. It works. My next step was about to find two ids #personFindByIdForm and #find-result. I can't do it since document is already loaded if I'm right. How could I do this ?
And the second question - if I add any js code into the div that will be loaded into another div, will that js code run (why is it not running)?
Like:
$("#div-2").load('/any-url #div-1');
<div id='div-1'>
<script>console.log('Any JS')</script>
</div>
Thank you.
You can make sure the items are loaded this way:
$("#div-2").load('/any-url #div-1', function(){
//here all the items loaded will be accessible
});

Underscore and bootstrap datetimepicker

I am trying to get bootstrap datetimepicker to work from https://github.com/Eonasdan/bootstrap-datetimepicker on my webapp. Due to the fact that I am using templates, I cant have the script tags needed to initialize the datetimepicker inside the template script tags.
$("#datetimepicker1").datetimepicker(); //where should this go
<script type="text/template" id="manage-todos-template">
<div id="user-info">
Signed in as <%= Parse.User.current().get("username") %> (Log out)
</div>
<br>
<div>
<textarea name="styled-textarea" maxlength="50" id="styled" onfocus="this.value=''; setbg('#e5fff3');" onblur="setbg('white')">Enter promo here </textarea>
</div>
<div class="container">
<div class="row">
<div class='col-sm-6'>
<div class="form-group">
<div class='input-group date' id='datetimepicker1'>
<input type='text' class="form-control" />
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"> </span>
</span>
</div>
</div>
</div>
<button href="#" class="submitPromo">Submit</button>
</script>
//render
render: function() {
$('#datetimepicker1').datetimepicker();
}
This is a common pattern where you need to initialize some third part component on top of your rendered html. What you basically need to do is first render your HTML and then call your third party component on the appropriate element. Keep in mind that if you haven't yet attached your view's element to the DOM (as is often the case when you are rendering a view) you can still traverse it's el using $el.find.
For example
render: function () {
var template = _.template($('#mytemplate').html());
this.$el.html(template);
this.$el.find('#datetimepicker1').datetimepicker();
return this;
}
And a link to a sjbin

Categories