When clicking very quickly on Angularjs app page doesn't load - angularjs

FYI - I am very new to Angular...not my code mostly from tutorial on Lynda which I am playing with.
I noticed when I am doing a type of "pagination" where I am showing different elements from a data.json file, the page doesn't load if I click page back anchor links too quickly to show the next or previous item. The culprit begins somewhere as a result of the anchor tags here (details.html file) / in the controller of details. I am wondering if it's async/await not being used issue.
<div class="container">
<div class="row">
<div class="col-12 mt-3">
<div class="card">
<div class="card-header d-flex align-items-start justify-content-between">
<h1 class="card-title my-0">{{artists[whichItem].name}}</h1>
<nav class="btn-group">
<a class="btn btn-sm btn-secondary"
href="#/details/{{prevItem}}"><</a>
<a class="btn btn-sm btn-secondary"
href="#/">•Home</a>
<a class="btn btn-sm btn-secondary"
href="#/details/{{nextItem}}">></a>
</nav>
</div>
<div class="card-body"
ng-model="artists">
<h4 class="card-title text-dark mt-0">{{artists[whichItem].reknown}}</h4>
<img class="float-left mr-2 rounded"
ng-src="images/{{artists[whichItem].shortname}}_tn.jpg"
alt="Photo of {{artists[whichItem].name}}">
<div class="card-text text-secondary">{{artists[whichItem].bio}}</div>
</div>
</div>
</div>
</div>
</div>
In the meantime - By searching different things online I added a
.otherwise({
redirectTo: '/'
});
a redirect so something shows up. It'd be great if someone can please help explain what's causing that and how to fix it. I am posting the code below. I also added console.logs to help me debug in my controller, but I was not successful.
My smaller controller - (controllers.js):
var myControllers = angular.module('myControllers', []);
myControllers.controller('SearchController', function MyController($scope, $http) {
$scope.sortArtistBy = 'name';
$http.get('js/data.json').then(
(response) => $scope.artists = response.data
);
});
myControllers.controller('DetailsController', function MyController($scope, $http, $routeParams) {
$http.get('js/data.json').then(
function(response) {
$scope.artists = response.data
$scope.whichItem = $routeParams.itemId;
if($routeParams.itemId > 0){
$scope.prevItem = Number($routeParams.itemId) - 1;
console.log("I am going to 18")
} else {
console.log("I am going to 20")
$scope.prevItem = $scope.artists.length - 1;
}
if($routeParams.itemId < $scope.artists.length - 1){
console.log("I am going to 25")
$scope.nextItem = Number($routeParams.itemId) + 1;
} else {
console.log("I am going to 28")
$scope.nextItem = 0;
}
}
);
});
My main app controller (app.js):
var myApp = angular.module('myApp', [
'ngRoute',
'myControllers'
]);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'js/partials/search.html',
controller: 'SearchController'
})
.when('/details/:itemId', {
templateUrl: 'js/partials/details.html',
controller: 'DetailsController'
})
.otherwise({
redirectTo: '/'
});
}]);
My (index.html) file:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title>AngularJS</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="lib/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="css/style.css">
<script src="lib/angular/angular.min.js"></script>
<script src="lib/angular/angular-route.min.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body class="bg-secondary">
<div ng-view></div>
<script src="lib/jquery/jquery.min.js"></script>
<script src="lib/bootstrap/popper.min.js"></script>
<script src="lib/bootstrap/bootstrap.min.js"></script>
</body>
</html>

One approach is to cache the data in a service:
app.service("dataService", function($http) {
var cache;
this.get = () => {
cache = cache || $http.get('js/data.json');
return cache;
};
})
Then in the controller:
app.controller('DetailsController', function MyController($scope, dataService, $routeParams) {
dataService().then(
function(response) {
$scope.artists = response.data
$scope.whichItem = $routeParams.itemId;
//...
}
);
});
By caching the $http promise, the app avoids repeating identical requests to the server.

Related

Not able to inject resolved object from ui-route change into the controller

I am trying to access an http get response called during route change using ui route. The resolve itself happens but i am unable to access the response. I have tried some approaches in "listcontroller" which is shown. I am using a sample httpget url found in the internet for test. Angular version: v1.2.32. ui-route: 1.0.15.
script.js
var app = angular.module("Rasp", ["ui.router"])
.config(['$stateProvider', '$urlRouterProvider',function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state("ipList", {
url: "/ipList",
templateUrl: "templates/list.html",
controller: "listController",
resolve: {
SensorIP : function($http){
$http.get('https://httpbin.org/ip')
.then(function(response){
console.log('res');
console.log(response);
return response.data.origin;
});
}
}
})
.state("home", {
url: "/home",
templateUrl: "templates/home.html",
controller: "homeController"
});
}])
.controller("RaspController", ['$scope', '$http', function ($scope, $http) {
$scope.getDetails = function () {
// $http.get('https://httpbin.org/ip')
// .then(function (response) {
// console.log(response);
// $scope.response = response;
// },
// function (error) { console.log(error); }
// );
// };
}])
.controller("homeController", ['$scope', function ($scope) {
}])
.controller("listController", ['$scope','SensorIP',function ($scope,SensorIP) {
$scope.sensorList = SensorIP;
var vm = this;
this.list1 = SensorIP;
var logfunc = function() {console.log($scope.sensorlist)};
}])
list.html
<div>
{{list1}}
{{sensorlist}}
<button class="btn btn-danger navbar-btn" ng-click="logfunc()">click</button>
</div>
home.html
<h4>Click on "Get IP List" to get the list of IPs</h4>
<a ui-sref="ipList"><button id="button" >Get IP List</button></a>
index.html
<!DOCTYPE html>
<head>
<title>Title(To be changed)</title>
<!--JS-->
<script type="text/javascript" src="../node_modules/angular/angular.js"></script>
<script type="text/javascript" src="../node_modules/#uirouter/angularjs/release/angular-ui-router.js"></script>
<script type="text/javascript" src="script.js"></script>
<!-- -->
<!--CSS-->
<link rel="stylesheet" href="../css/style.css">
<!-- -->
</head>
<body>
<div ng-app="Rasp">
<div ng-controller="RaspController">
<div class="sidenav">
<!--
<a ui-sref="home" id="dot-button"><button class="btn btn-danger navbar-btn" >Home</button></a>
<a ui-sref="ipList" id="dot-button"><button class="btn btn-danger navbar-btn" >IP List</button></a>
-->
<a ui-sref="home">home</a>
<a ui-sref="ipList" >ipList</a>
</div>
<div>
<ui-view id="uiview"></ui-view>
</div>
</div>
</div>
</body>

Angular loading Controllers and Services

I am using Angularjs for my application.I am having one common page which has header and footer which i am making common for all pages.Thats y i am placing it in one common html.Only contents code i am placing in other html pages.
As i am using one common page i am loading all controllers and all Services that i am using in the application.
Here is my commonpage.html
<!DOCTYPE html>
<html lang="en" data-ng-app="adminApp">
<head>
</head>
<body>
<!--Here is header code-->
<div class="LeftMenu">
<ul class="navbar">
<a href="#!/admindashboardhome" title="Dashboard"><li>
<span>Dashboard</span></li>
</a>
<a href="#!/examinationhalltickets" title="Declaration"><li>
<span>Examination Form</span></li>
</a>
<a href="#!/collegedetails" title="Declaration"><li>College
Details</li>
</a>
</ul>
</div>
<!--followed by footer code-->
<div data-ng-view> <!--ng-view-->
</div>
<!--Here i am loading all controllers and services related to application-->
<script
src="resources/angular/controller/admin/AdminExamController.js">
</script>
<script src="resources/angular/service/admin/AdminExamService.js">
</script>
<!-- And many more in same fashion-->
</body>
</html>
The doubt i am having is,is it necessary to place all controllers and services like i am doing because i am facing performance issue even though i am connected to strong internet it loads very slow.As i am placing all in one page it is loading all controllers and services everytime.If i place controllers in their respective html then i am getting error like ExamController.js or any .js Controller not defined.Is there any other way that i can load all controllers and services so that i can increase the performance of the application?
I think this is what your looking for
app.js
/* Module Creation */
var app = angular.module ('adminApp', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function($routeProvider, $controllerProvider){
/*Creating a more synthesized form of service of $ controllerProvider.register*/
app.registerCtrl = $controllerProvider.register;
function loadScript(path) {
var result = $.Deferred(),
script = document.createElement("script");
script.async = "async";
script.type = "text/javascript";
script.src = path;
script.onload = script.onreadystatechange = function (_, isAbort) {
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
if (isAbort)
result.reject();
else
result.resolve();
}
};
script.onerror = function () { result.reject(); };
document.querySelector("head").appendChild(script);
return result.promise();
}
function loader(arrayName){
return {
load: function($q){
var deferred = $q.defer(),
map = arrayName.map(function(name) {
return loadScript(name+".js");
});
$q.all(map).then(function(r){
deferred.resolve();
});
return deferred.promise;
}
};
}
$routeProvider
.when('/view2', {
templateUrl: 'view2.html',
resolve: loader(['Controller2'])
})
.when('/bar',{
templateUrl: 'view1.html',
resolve: loader(['Controller1'])
})
.otherwise({
redirectTo: document.location.pathname
});
}]);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-route.min.js"></script>
</head>
<body ng-app="adminApp">
<!--Here is header code-->
<div class="LeftMenu">
<ul class="navbar">
<a href="#!/admindashboardhome" title="Dashboard"><li>
<span>Dashboard</span></li>
</a>
<a href="#!/examinationhalltickets" title="Declaration"><li>
<span>Examination Form</span></li>
</a>
<a href="#!/collegedetails" title="Declaration"><li>College
Details</li>
</a>
</ul>
</div>
<!--followed by footer code-->
<div data-ng-view> <!--ng-view-->
</div>
<!--Here i am loading all controllers and services related to application-->
<script
src="app.js">
</script>
<!-- And many more in same fashion-->
</body>
</html>
Controller 1.js
(function(val){
'use strict';
angular.module('Controller1App', [])
.controller('Controller1', ['$http','$rootScope','$scope','$window', function($http,$rootScope, $scope, $window){
//Your code goes here
}])
})(this);
Controller 2.js
(function(val){
'use strict';
angular.module('Controller2App', [])
.controller('Controller2', ['$http','$rootScope','$scope','$window', function($http,$rootScope, $scope, $window){
//Your code goes here
}])
})(this);
Refer https://plnkr.co/edit/cgkgG5PCwJBVOhQ1KDW2?p=preview

Why do I keep getting the $[injector:modulerr] uncaught error when all dependencies have been injected?

Below is my index.html page which has two buttons which links to 2 different views which i intend to show using angular routing.
Below is my
HTML
<!DOCTYPE html>
<html>
<head>
<title>PR_APP</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-route.js"></script>
<script src="js/main.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="new_pr_app">
<h2>Please select an option</h2><br>
<div ng-controller="view_controller">
<button id="view_details" ng-click="view()">View Details</button>
</div>
<div ng-controller="update_controller">
<button id="update_details" ng-click="update()">Update Details</button>
</div>
<div ng-view>
</div>
</body>
Below is my main.js file which houses both above mentioned controller and logic for angular routing.
main.js
var app = angular.module('new_pr_app', ['ngRoute']);
app.config('$routeProvider','$locationProvider', function($routeProvider,$locationProvider){
$routeProvider.when("/update",
{
templateUrl:"update.html",
controller: "update_controller"
})
.when("/view",
{
templateUrl: "view.html",
controller: "view_controller"
});
});
app.controller("view_controller",function($scope, $location, http_factory){
$scope.view = function(){
$location.path("/view");
}
$scope.result =[];
http_factory.get_request().then(function(response){
$scope.result = response.data;
});
});
app.controller("update_controller",function($scope, $location, http_factory){
$scope.update_details = function(){
$location.path("/update");
}
$scope.names = [];
http_factory.get_request().then(function(response){
$scope.names = response.data;
});
});
I have another file called services.js which has a service factory to get details from a json file using an http get.
My only problem seems to be in the above main.js which gives the error below everytime index.html loads
angular.js:88 Uncaught Error: [$injector:modulerr]
Your config is wrong. You pass in a string as the first (and second argument), while the .config(..) function, expects a function to be passed in (or an array).
In your code, you simply forgot to wrap the arguments in an array. Here's how it should look:
app.config(['$routeProvider','$locationProvider',
function($routeProvider,$locationProvider){
$routeProvider.when("/update",
{
templateUrl:"update.html",
controller: "update_controller"
})
.when("/view",
{
templateUrl: "view.html",
controller: "view_controller"
});
}]);
Note the [ and ] wrapping the content
You can check with below code.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-route.js"></script>
<body ng-app="new_pr_app">
<h2>Please select an option</h2><br>
<div ng-controller="view_controller">
<button id="view_details" ng-click="view()">View Details</button>
</div>
<div ng-controller="update_controller">
<button id="update_details" ng-click="update_details()">Update Details</button>
</div>
<div ng-view>
</div>
<script>
var app = angular.module('new_pr_app', ['ngRoute']);
app.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider){
$routeProvider.when("/update",
{
template:"update template"
// controller: "update_controller"
})
.when("/view",
{
template: "view template"
// controller: "view_controller"
});
}]);
app.controller("view_controller",function($scope, $location){
$scope.view = function(){
$location.path("/view");
}
});
app.controller("update_controller",function($scope, $location){
$scope.update_details = function(){
$location.path("/update");
}
});
</script>
</body>
</html>

Passing Data between state Providers in angular

Im looking to pass data between 2 controllers in Angular, Below is code i started
There are 2 views one with input field and other with a link.
when i click on link in the second view i should be able to set a state and state data should be populated in input field in first field.
I tried several approaches but im missing something.
Can someone help me here
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>Hello AngularJS</title>
<script data-require="angular.js#1.2.10" data-semver="1.2.10" src="http://code.angularjs.org/1.2.10/angular.min.js"></script>
<script src="http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(['$stateProvider','$stateProvider', '$urlRouterProvider', function ($stateProvider,$urlRouterProvider) {
var addBook = {
name: 'addBook',
url: '/addBook',
template: '<h2>Add A book</h2> Data from View <input type="text" ng-model={{input-text}}>' ,
data:""
},
viewBookv = {
name: 'viewBookv',
url: '/viewBook',
template: '<h2>View A book</h2><span class="glyphicon glyphicon-edit">Edit</span> ' ,
};
$stateProvider.state(addBook, "controller: editUserCtrl");
$stateProvider.state(viewBookv, "controller: editUserCtrl");
}])
myApp.controller('editUserCtrl', function($scope, $stateParams) {
$scope.paramOne = $stateParams.data;
$scope.edit = function () {
event.preventDefault();
$state.go("addBook");
}
})
myApp.controller('mainController',function($scope, $rootScope, $state,$window){
$scope.addBook=function(){
$state.go("addBook");
};
$scope.viewbookls= function(){
$state.go("viewBookv");
};
})
</script>
</head>
<body>
<div class="container">
<div class="col">
<div class="col-md-3" ng-controller="mainController">
<ul class="nav">
<li> View Book </li>
<li> Add Book </li>
</ul>
</div>
<div class="col-md-9">
<div ui-view></div>
</div>
</div>
</div>
</body>
</html>
Typically in angular the way to share state between controllers is using a service. So the way it's usually set up is to setup a service then import that service into the relevant controllers, and that data gets shared between them. I've modified your example above to follow this pattern(I'm not quite sure what you were trying to do)
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>Hello AngularJS</title>
<script data-require="angular.js#1.2.10" data-semver="1.2.10" src="http://code.angularjs.org/1.2.10/angular.min.js"></script>
<script src="http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider,$urlRouterProvider) {
var addBook = {
name: 'addBook',
url: '/addBook',
template: '<h2>Add A book</h2> Data from View <button ng-click="updateBook()">Update</button> <input type="text" ng-model="inputText">' ,
controller: "addBookCtrl",
data:""
},
viewBookv = {
name: 'viewBooks',
url: '/viewBook',
template: '<h2>View A book</h2><div ng-repeat="book in bookList">{{book}}</div>',
controller: "viewBookCtrl",
};
$stateProvider.state('addBook', addBook);
$stateProvider.state('viewBooks', viewBookv);
}])
myApp.controller('addBookCtrl', function($scope, bookService) {
$scope.updateBook = function(){
console.log( $scope.inputText)
bookService.books.push($scope.inputText);
}
})
myApp.controller('viewBookCtrl', function($scope, bookService) {
$scope.bookList = bookService.books
})
myApp.factory('bookService', function() {
var bookService = {};
bookService.books = [];
return bookService;
});
myApp.controller('mainController',function($scope, $rootScope, $state,$window){
$scope.addBook=function(){
$state.go("addBook");
};
$scope.viewbookls= function(){
$state.go("viewBooks");
};
})
</script>
</head>
<body>
<div class="container">
<div class="col">
<div class="col-md-3" ng-controller="mainController">
<ul class="nav">
<li> View Book </li>
<li> Add Book </li>
</ul>
</div>
<div class="col-md-9">
<div ui-view></div>
</div>
</div>
</div>
</body>
</html>
What this example does, is in the text box for add book, you type in the name (then click update), this appends it to an array so every time you do it you'll get a new element on that array. From there head over to the view books page, and you'll see all the different things you typed in.

Ionic Controller and Service Structure

I'm pretty new to Ionic and AngularJS. I tried to create a note app but my controllers.js did not seem to understand services.js. What do I have to do to fix this problem. Thanks in advance.
And this is my code look like
app.js
(function() {
var app = angular.module('starter', ['ionic', 'starter.controllers' ,'starter.services'])
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('list', {
url: '/list',
templateUrl : 'templates/list.html'
});
$stateProvider.state('edit', {
url: '/edit/:Id',
templateUrl : 'templates/edit.html',
controller : 'EditCtrl'
});
$stateProvider.state('add', {
url: '/add',
templateUrl : 'templates/edit.html',
controller : 'AddCtrl'
});
$urlRouterProvider.otherwise('/list');
});
app.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
}());
controllers.js
angular.module('starter.controllers', [])
.controller('ListCtrl', function($scope, NoteStore) {
$scope.notes = NoteStore.list();
});
.controller('EditCtrl', function($scope, $state, NoteStore) {
$scope.title = "Edit";
$scope.note = angular.copy(NoteStore.get($state.params.Id));
$scope.save = function() {
NoteStore.update($scope.note);
$state.go('list')
};
});
.controller('AddCtrl', function($scope, $state, NoteStore) {
$scope.title = "New Note";
$scope.note = {
id: new Date().getTime().toString()
};
$scope.save = function() {
NoteStore.create($scope.note);
$state.go('list')
};
});
services.js
angular.module('starter.services', [])
.factory('NoteStore', function() {
var notes = [];
return {
list : function() {
return notes;
},
get : function(noteId) {
for (var i = 0; i < notes.length; i++) {
if (notes[i].id === noteId) {
return notes[i];
}
}
return undefined;
},
create : function(note) {
notes.push(note);
},
update : function(note) {
for (var i = 0; i < notes.length; i++) {
if (notes[i].id === note.id) {
notes[i] = note;
return;
}
}
return undefined;
}
}
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="cordova.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="starter">
<ion-pane>
<ion-nav-bar class="bar-assertive">
<ion-nav-back-button class="button-clear">
<i class="ion-arrow-left-c"></i> Back
</ion-nav-back-button>
</ion-header-bar>
<ion-nav-view>
</ion-nav-view>
</ion-pane>
</body>
</html>
list.html
<ion-view view-title="My Notes">
<ion-nav-buttons side="right">
</ion-nav-buttons>
<ion-content ng-controller="ListCtrl">
<div class = "list">
<a href="#/edit/{{note.id}}" class = "item" ng-repeat = "note in notes">
<h2>{{note.title}}</h2>
<p>{{note.description}}</p>
</a>
</div>
</ion-content>
</ion-view>
edit.html
<ion-view view-title="{{title}}">
<ion-content>
<div class="list card">
<div class="item item-input">
<input type="text" placeholder="Title" ng-model="note.title">
</div>
<div class="item item-input">
<textarea rows="5" placeholder="Description" ng-model="note.description"></textarea>
</div>
</div>
<div class="padding">
<button class="button button-positive button-block" ng-click="save()">Save</button>
</div>
</ion-content>
</ion-view>
When you separate it into separate files first make sure you load the files in your index.html
so for each controller or service js file you will need in your index.html
<script type="text/javascript" src="//path to js file"></script>
The next thing you need to do is inject your services and your controller into your main app.module which you did do here:
var app = angular.module('starter', ['ionic', 'starter.controllers' ,'starter.services'])
You also need to inject your service into you controller which you did not do so in
angular.module('starter.controllers', [])
you need to inject 'stater.services'
so it should look like
angular.module('starter.controllers', ['starter.services'])
then in your controller you can inject whatever factory you need
.controller('EditCtrl', function(NoteStore){})
each module needs to have the other modules it depends on injected into it.
For example on my app i also inject ionic into my controllers and services.
That should get it working for you. If you want me to post more examples let me know.
Found the problem!!!
In the controllers.js you can't end a controller and start another.
If you want to use multiple controllers on the same JS file, you have to use semicolon only on the last controller.
I.E. You have 3 controllers
.controller('ListCtrl', function(){})
.controller('EditCtrl', function(){})
.controller('AddCtrl', function(){});
Only the last controller have to end with semicolon.

Resources