Angular/Ionic Views - where to put controller? - angularjs

I have an Ionic app that has two views:
Home
Activity
The 'Home' view shows static info with a login screen that takes users to the 'Activity' page where they can see updated info from a $http request to my REST. I can make the call work on a single page, but I dont know where to put the controller when its being used on a view other than the main view and Im unsure how to handle the duplicate specification of the ng-app; its being called in both the 'home' view and the 'activity' view.
Here is my 'Home'
<!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">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/routes.js"></script>
<script src="js/services.js"></script>
<script src="js/directives.js"></script>
<!-- Only required for Tab projects w/ pages in multiple tabs
<script src="lib/ionicuirouter/ionicUIRouter.js"></script>
-->
</head>
<body ng-app="app" animation="slide-left-right-ios7">
<div>
<div>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button class="button-icon icon ion-ios-arrow-back">Back</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</div>
</div>
</body>
</html>
and here is my 'Activity' view:
<ion-view title="Activity">
<ion-content overflow-scroll="true" padding="true" class="has-header">
<div ng-app="app" ng-controller="users">
<div style="width:100%; text-align:center;">
<table class="pure-table">
<thead>
<tr><td>Device ID</td><td>First Name</td><td>Last Name</td><td>Activity</td></tr>
</thead>
<tbody>
<tr ng-repeat="x in names">
<td>{{ x.Regid }}</td><td>{{ x.Fname }}</td><td>{{ x.Lname }}</td><td>{{ x.activity }}</td>
</tr>
<tbody>
</tbody></tbody></table></div>
<button class="button button-full button-light" id="refresh">
Refresh
</button>
</div>
<div class="bar bar-footer bar-stable">
<div class="title"></div>
</div>
<script>
var app = angular.module('app', []);
app.controller('users', function($scope, $http, $interval) {
$http.get("call to REST.php")
.then(function (response) {$scope.names = response.data.records;});
$interval(MyCtrl, 3000);
});
function callAtInterval(){
//console.log("Interval Occured");
//window.location.reload();
//$state.reload();
}
function MyCtrl($scope )
{
$scope.updateFromModel = 'Initial Value';
setTimeout( function()
{
console.log( 'automatically update view?' );
$scope.updateFromModel = "It's been updated";
$scope.$apply();
}, 1000 );
}
$('#refresh').click(function() {
location.reload();
});
</script>
</ion-content>
</ion-view>
and here are my routes:
angular.module('app.routes', [])
.config(function($stateProvider, $urlRouterProvider) {
.state('login', {
url: '/home',
templateUrl: 'templates/login.html',
controller: 'loginCtrl'
})
.state('activity', {
url: '/activity',
templateUrl: 'templates/activity.html',
controller: 'activityCtrl'
})
$urlRouterProvider.otherwise('/home')
});

You can add controllers in controller.js file same like following code:
app.controller('MyController1', function($scope) {
//write controller specific code here...
});
app.controller('MyController2', function($scope) {
//write controller specific code here...
});
... so on
Or you can define in <script> tag too right after define your app module:
var app = angular.module('app', []);
app.controller('MyController1', function($scope) {
//write controller specific code here...
});
app.controller('MyController2', function($scope) {
//write controller specific code here...
});
... so on

I just figured it out. The controller goes in the controller.js under the controller thats already been established for the activity route.

You have to create a controller for each view/session in a isolated js file (controllers.js) and then declare as a angular module of your app.
Check out the official Ionic Framework Tutorial recommendations
https://ccoenraets.github.io/ionic-tutorial/create-angular-controller.html
angular.module('starter.controllers', [])
.controller('loginCtrl', function ($scope) {
$scope.LoginForm = {};
$scope.Login = function() {
alert($scope.LoginForm.User);
alert($scope.LoginForm.Password);
location.href = "#tab/qr-reader";
};
})
more controllers
...

Related

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

Ionic delete button in header view toggle delete button in list view

I have a simple list of items and want to have a button in the header that shows and hides a delete button next to each list item. My header and content are made up of separate views.
After much reading, it seems a controller is attached to a view rather than a state, so I need to have a separate controller for each view (one controller for the header and one controller for the content). As I can't share variables between controllers, what is the best way to have a button in one view (header.html) show/hide buttons in a list in a different view (content.html)?
My HTML is below:
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">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<!--For users deploying their apps to Windows 8.1 or Android Gingerbread, platformOverrided.js
will inject platform-specific code from the /merges folder -->
<script src="js/platformOverrides.js"></script>
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="Scripts/angular-resource.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="starter">
<ion-view view-title="Playlists">
<div ui-view="header"></div>
<div ui-view="content"></div>
</ion-view>
</body>
</html>
header.html
<ion-header-bar class="bar-positive">
<div class="buttons">
<button class="button button-icon icon ion-ios-minus-outline"
ng-click="data.showDelete = !data.showDelete"></button>
</div>
<h1 class="title">my test app</h1>
</ion-header-bar>
content.html
<ion-content class="has-header has-footer" overflow-scroll="true">
<ion-list show-delete="data.showDelete">
<ion-item ng-repeat="movie in movies" href="#/home/{{movie.id}}">
{{movie.title}}
<ion-delete-button class="ion-minus-circled"
ng-click="onItemDelete(movie)">
</ion-delete-button>
<ion-option-button class="button-assertive" ui-sref="editMovie({id:movie.id})">Edit</ion-option-button>
</ion-item>
</ion-list>
</ion-content>
and my js is below.....
app.js
angular.module('starter', ['ionic', 'ngResource', 'starter.controllers', 'starter.services'])
.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 (cordova.platformId === "ios" && window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function ($stateProvider, $urlRouterProvider) {
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
views: {
'header': {
templateUrl: 'templates/header.html',
controller: 'headerCtrl'
},
'content': {
templateUrl: 'templates/content.html',
controller: 'contentCtrl'
},
'footer': {
templateUrl: 'templates/footer.html'
}
}
});
});
controllers.js
angular.module('starter.controllers', [])
.controller('headerCtrl', function ($scope) {
$scope.showDelete = function () {
$scope.data.showDelete = !$scope.data.showDelete;
};
})
.controller('contentCtrl', function ($scope, $state, $stateParams, Movie) {
// populate list withg all items from database
$scope.movies = Movie.query();
// handle delete button click
$scope.onItemDelete = function (movie) {
$scope.movies.splice($scope.movies.indexOf(movie), 1);
movie.$delete();
$scope.data.showDelete = false;
};
});
You actually can share variables between controllers, by using what Angular calls a "service".
AngularJS: How can I pass variables between controllers?

Angularjs - $routerProvider's 'when' function and 'templateUrl' navigate to 'wrong' path?

My dir's structure is like:
---/public
|
---index.html
---shop.html
|
---/js
|
---index.js
---index_controller.js
---/lib
---/css
---/plugins
|
---...
my index.html:
<!doctype html>
<html class="signin no-js" lang="">
<head>
<meta charset="utf-8">
<meta name="description" content="Flat, Clean, Responsive, application admin template built with bootstrap 3">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<title>Index</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.css">
<link rel="stylesheet" href="css/themify-icons.css">
<link rel="stylesheet" href="css/animate.min.css">
<link rel="stylesheet" href="css/skins/palette.css">
<link rel="stylesheet" href="css/fonts/font.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/lib/angular/angular.js"></script>
<script src="js/lib/angular/angular.min.js"></script>
<script src="js/lib/angular/angular-route.js"></script>
<script src="js/lib/angular/angular-route.min.js"></script>
<script src="js/index_controller.js"></script>
<script src="js/index.js"></script>
<script src="plugins/modernizr.js"></script>
</head>
<body class="bg-primary" ng-app="myApp.index">
<div class="cover" style="background-image: url(img/cover3.jpg)"></div>
<div class="overlay bg-primary"></div>
<div class="center-wrapper">
<div class="center-content">
<div class="row">
<div class="col-xs-10 col-xs-offset-1 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4">
<section class="panel bg-white no-b">
<ul class="switcher-dash-action">
<li class="active">Index</li>
</ul>
<div class="p15" ng-controller="IndexCtrl">
<form role="form" >
<div >
<button class="btn btn-primary btn-lg btn-block" ng-click='testRoute()'>
TestRoute
</button>
</div>
</form>
</div>
</section>
<p class="text-center">
Copyright ©
<span id="year" class="mr5"></span>
</p>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var el = document.getElementById("year"),
year = (new Date().getFullYear());
el.innerHTML = year;
</script>
</body>
</html>
And shop.html renders the following: (only for test use):
SHOP
And index_controller.js is :
function IndexCtrl($scope, $http, $location, $route, $window) {
$scope.testRoute = function() {
console.log(">>>TestRoute>>>");
$location.url('/shop');
}
}
function ShopCtrl() {
console.log("ShopCtrl");
}
And index.js:
'use strict';
//Angular-js
var module = angular.module('myApp.index', ['ngRoute']);
module.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/shop', {templateUrl: 'shop.html', controller: ShopCtrl
});
}]);
/*My Controllers*/
module.
controller('IndexCtrl', ['$scope', '$http', '$location', '$route', '$window', IndexCtrl]);
module.
run([
'$rootScope', '$location',
function($rootScope, $location) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
var nextTemplate = next.templateUrl;
var nextController = next.controller;
console.log("location.path:" + $location.path());
console.log('Template Starting to leave %s to go to %s\n', "", nextTemplate);
console.log('Controller Starting to leave %s to go to %s\n', "", nextController);
});
}
]);
And when I type "http://localhost:6001/index.html" in Chrome's address bar, it renders:
After clicking Test Route button, it changes to:
Only the url address changes, and it seems strange:
"http://localhost:6001/index.html#/shop"
Whereas I need
"http://localhost:6001/shop"
Chrome's console shows:
My problem is: how to render shop.html and how to navigate to /guoguo path properly, using code like:
$routeProvider.when('/shop', {templateUrl: 'shop.html', controller: ShopCtrl
});
I am pretty new to Angular. Maybe I am not thinking in the angularjs approach. Thanks for your points.
It is a mix of issues for your .html# being shown. Try this.
1: Add in the first line of head tags
<head><base href="/">
...
</head>`
2: Use this $locationProvider.html5Mode(true);
app.config(function($routeProvider,$locationProvider){
$routeProvider
.when('/',{
templateUrl: 'views/home.html',
controller:'homeCtrl'
})
.when('/about',{
templateUrl: 'views/about.html',
controller:'aboutCtrl'
})
.otherwise({
redirectTo: '/home'
});
$locationProvider.html5Mode(true);
});
This should remove the # from the page. But in your server make index.html as the default file serving for the path http://localhost:6001/ then it will load http://localhost:6001/index.html as http://localhost:6001/
I finaly get to know that AngularJS is a SPA(Single Page App) based framwork. If I simply jump to another html, the page will load another ng-app, which has no relation to origin app(the bootstrap has been restarted).
What solution I take is to use ng-view inside the index html. It allows to load different ng-view(which is in '<div></div>' from other html file), and config the routeProvider by declaring template url and controller.
I will paste the complete code later, thanks for you all !!!

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.

AngularJS with loading external page with controller

I have a quick question on loading external page with route. I am quite new to AngularJS.
var app = angular.module('app', []);
$routeProvider.when('/list', {
templateUrl: '/list.html'
})
Load up the page, but within the list.html there is controller defined.
list.html:
<script>
app.controller('test', function(){
console.log('test');
});
</script>
<div ng-controller="test">
</div>
The above code will throw me an error as test is undefined function, unless if i place the app.controller('test') to the parent page.
So i can't place controller on external .html files?
Updated link below:
http://plnkr.co/edit/YC6P9W1VfzX8XOyrynCP?p=preview
You have to create a separate script.js and should load in main html page during execution of main page or during click of the link
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular-route.min.js"></script>
<script src="script.js"></script>
<script src="testscript.js"></script>
</head>
<body ng-controller="home">
<h1>Hello Plunker! {{change}}</h1>
Test
<ng-view></ng-view>
</body>
</html>
testscript.js
function test2($scope){
console.log('succeed');
};
script.js
// Code goes here
var app = angular.module('app', ['ngRoute']);
app.controller('home', function($scope){
$scope.change = "change";
$scope.test = function(){
console.log('clicked');
}
});
app.config(function($routeProvider){
$routeProvider.when('/test', {
templateUrl: 'test.html',
controller: function(){
console.log('here');
}
})
});

Resources