I"m following the Angular Tutorials and I see in their example that ng-scope is added to each element with a directive.
https://docs.angularjs.org/guide/scope
But my own code does NOT add the ng-scope for each directive, every thing seems to work from rendering the data, but for some reason this CSS class is not added.
My Application has started life from a Yeoman.io starter project so I'm not sure if something in that project has caused the issue.
https://github.com/diegonetto/generator-ionic
Ive added the www code as a .zip in my dropbox:
https://www.dropbox.com/s/hn36080isu83vw5/www.zip
Tutorial Example
My Example
HTML
<h1 style="margin-top: 50px;">Scope Heirachy</h1>
<div class="show-scope-demo">
<div ng-controller="ParentGreetController">
Hello {{name}}!
</div>
<div ng-controller="ChildListController">
<ol>
<li ng-repeat="name in names">{{name}} from {{department}}</li>
</ol>
</div>
</div>
Controller.JS
var moduleTest = angular.module('test', []);
moduleTest
.controller('ParentGreetController', ['$scope', '$rootScope', function ($scope, $rootScope)
{
$scope.name = 'World';
$rootScope.department = 'Angular';
}])
// We will access name which is in both scopes
.controller('ChildListController', ['$scope', function ($scope)
{
$scope.names = ['Igor', 'Misko', 'Vojta'];
}]);
App.JS
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'invoice1', 'invoice2', 'invoice3', 'test', 'myService'])
.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) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: 'AppCtrl'
})
.state('app.search', {
url: "/search",
views: {
'menuContent': {
templateUrl: "templates/search.html"
}
}
})
.state('app.browse', {
url: "/browse",
views: {
'menuContent': {
templateUrl: "templates/browse.html"
}
}
})
.state('app.playlists', {
url: "/playlists",
views: {
'menuContent': {
templateUrl: "templates/playlists.html",
controller: 'PlaylistsCtrl'
}
}
})
.state('app.scopeHeirachy', {
url: "/scopeHeirachy",
views: {
'menuContent': {
templateUrl: "templates/sample/scopeHeirachy.html"
}
}
})
;
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/playlists');
});
I have tried setting debugInfoEnabled on & off using the following
.config(function($stateProvider, $urlRouterProvider, $compileProvider) {
$compileProvider.debugInfoEnabled(false);
});
and
.config(function($stateProvider, $urlRouterProvider, $compileProvider) {
$compileProvider.debugInfoEnabled(true);
});
Check if the following lines of code are added in your javascript. This usually removes debug info i.e. Ng-scope. This is usually added to improve performance in production code.
$compileprovider.debuginfoenabled(false)
ionic-angular.js has overridden the addClass function.
Here is the snippet.
jqLite.prototype.addClass = function(cssClasses) {
var x, y, cssClass, el, splitClasses, existingClasses;
if (cssClasses && cssClasses != 'ng-scope' && cssClasses != 'ng-isolate-scope') {
//............
Because of the if condition ng-scope and ng-isolate-scope classes are not getting added even if the debuggingInfo is enabled.
Related
I'm new to Javascript. I'm building an app using Ionic.
First I created app using ionic start MyAPPOne tabs
Then I installed Cordova Text-to-SpeechPlugin
This is my app.js
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', '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 (window.cordova && window.cordova.plugins && 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) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.chats', {
url: '/chats',
views: {
'tab-chats': {
templateUrl: 'templates/tab-chats.html',
controller: 'ChatsCtrl'
}
}
})
.state('tab.chat-detail', {
url: '/chats/:chatId',
views: {
'tab-chats': {
templateUrl: 'templates/chat-detail.html',
controller: 'ChatDetailCtrl'
}
}
})
.state('tab.account', {
url: '/account',
views: {
'tab-account': {
templateUrl: 'templates/tab-account.html',
controller: 'AccountCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
});
I want to add this code into my app.js.
angular.module('starter', ['ionic'])
.controller('AppCtrl', function($scope) {
$scope.data = {
speechText: ''
};
$scope.recognizedText = '';
$scope.speakText = function() {
TTS.speak({
text: $scope.data.speechText,
locale: 'en-GB',
rate: 1.5
}, function () {
// Do Something after success
}, function (reason) {
// Handle the error case
});
};
$scope.record = function() {
var recognition = new SpeechRecognition();
recognition.onresult = function(event) {
if (event.results.length > 0) {
$scope.recognizedText = event.results[0][0].transcript;
$scope.$apply()
}
};
recognition.start();
};
});
So how can I do it? I tried to merge this by pasted this code in app.js but when I checked this via ionic serve the app didn't show tabs. How can I merge this?
Replace this line
angular.module('starter', ['ionic'])
with
angular.module('starter.controllers')
We have a HTML5 app that uses a API accessible via http.get. I wish to keep the API URL address hidden from the public.
With this included in an app.js file, the javascript file is viewable.
$http.get('http://myAPIurl.com').success(function(data) {
The app is currently stored on a server that has PHP/MySQL capabilities.
Is there any way I can store my API URL in say a PHP file(which will hide contents) and then have something like an includes file within my app.js file.
https://jsfiddle.net/4y3cdpn8/
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', ['ionic','ngCordova'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
if(window.cordova && window.cordova.plugins.Keyboard) {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
// Don't remove this line unless you know what you are doing. It stops the viewport
// from snapping when text inputs are focused. Ionic handles this internally for
// a much nicer keyboard experience.
cordova.plugins.Keyboard.disableScroll(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('tabs', {
url: '/tab',
cache: false,
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tabs.home', {
url: '/home',
cache: false,
views: {
'home-tab' : {
templateUrl: 'templates/home.html'
}
}
})
.state('tabs.list', {
url: '/list',
cache: false,
views: {
'list-tab' : {
templateUrl: 'templates/list.html',
controller: 'ListController'
}
}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/home');
})
.controller('ListController', ['$scope', '$http', '$state','$stateParams', '$window', '$location', function($scope, $http, $state, $stateParams, $window, $location) {
$scope.query = '';
$scope.getOrders= function(query){
$http.get('http://myAPIurl.com').success(function(data) {
$scope.orders = data;
})
}
$state.go('tabs.home');
}
}]);
I am trying to set up a factory in my app.js of my ionic app. I have the following code that should work however my state provider is throwing me off and Im not sure where my states should be. I was suggested to use this app.js code to get my factory working however it leaves no room for my routes. I have tried different variations of the following with no lck. Thnk you in advance.
(function() {
'use strict';
angular
.module('starter', []) // In your real application you should put your dependencies.. ['ng...']
//.run(runFunction) // Just commenting to make it WORK HERE
.controller('MainCtrl', MainCtrl)
.factory('myService', myService);
// Just commenting to make it work here..
/*function runFunction($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 && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
})
}*/
MainCtrl.$inject = ['$scope', 'myService'];
function MainCtrl($scope, myService) {
function getSuccess(response) {
$scope.items = response.data;
}
function getError(response) {
console.log('Of course an error since the url is a invalid, but it should work with a valid url!');
}
myService.getAll()
.then(getSuccess)
.catch(getError);
}
function myService($http) {
var factory = {
getAll: getAll
};
return factory;
function getAll() {
return $http.get("url"); // it -> should be your URL
}
}
})();
// dont know where the config goes?
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('login', {
url: "/login",
cache: false,
controller: 'AccountCtrl',
templateUrl: "templates/login.html"
})
.state('list', {
url: "/list",
cache: false,
controller: 'ListCtrl',
templateUrl: "templates/list.html"
})
$urlRouterProvider.otherwise('/tab/dash');
});
I don't see you have included ui.router in your app. To work with $stateProvider you should place ui.router module in your depenencies, and should include angular-ui-router.js files in your project.
angular
.module('starter', ['ui.router']) // In your real application you should put your dependencies.. ['ng...']
//.run(runFunction) // Just commenting to make it WORK HERE
.controller('MainCtrl', MainCtrl)
.factory('myService', myService);
ui.router is the module that provides you $stateProvider.
After this .config can go along with module like .controller and .factory. Config is also defined on you app:
angular.module('starter', ['ui.router'])
.config(configFn) //configFn is the function you have in your .config
.controller('MainCtrl', MainCtrl)
.factory('myService', myService);
I have been making an app in AngularJS with Angular-ui-router based on Ionic Framework. It works perfect on the desktop in every web browser, but it does not show anything on my mobile (after build I run it on 2 devices). The problem is that it doesn't load template inside ui-view.
I have got an index.html file, the body section is below (in head section there is everything included):
<body ng-app="starter">
<div ui-view=""></div>
</body>
And the part of app.js - run and config.
angular.module('starter', ['ionic', 'ngStorage', 'ngAnimate', 'naif.base64', 'ui.router'])
.run(function($ionicPlatform, $rootScope, $location) {
$ionicPlatform.ready(function() {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
history = [];
$rootScope.$on('$routeChangeSuccess', function() {
history.push($location.$$path);
});
$rootScope.back = function () {
history.back();
};
})
.config(function($stateProvider, $urlRouterProvider) {
"use strict";
$stateProvider
.state('connectionCheck', {
url: '/',
controller: ['$scope', '$location', '$http',
function($scope, $location, $http) {
$http.get('http://pingurl.com')
.success(function(data) {
jdata = data;
if (data.status === "success") {
$location.path('/login');
}else{
$location.path('/error');
}
})
.error(function() {
$location.path('/error');
});
$scope.retry = function() {
$location.path('/');
};
}
]
})
.state('login', {
url: '/login',
templateUrl: 'login.html'
})
.state('main', {
url: '/main',
templateUrl: 'main.html',
controller: ['$scope', '$location', '$localStorage',
function($scope, $location, $localStorage) {
$scope.username = $localStorage.username;
$scope.token = $localStorage.token;
$scope.email = $localStorage.email;
$scope.goToAlerts = function() {
$location.path('/alerts');
};
$scope.goToSettings = function() {
$location.path('/settings');
};
$scope.goToLocation = function() {
$location.path('/location');
};
$scope.goToSymptoms = function() {
$location.path('/symptoms');
};
$scope.getClass = function(path) {
if ($location.path().substr(0, path.length) == path) {
return "active"
} else {
return ""
}
};
}
]
})
.state('error', {
url: '/error',
templateUrl: 'error.html'
})
.state('register', {
url: '/register',
templateUrl: 'register.html',
})
.state('push', {
url: '/push',
templateUrl: 'push.html',
})
.state('alerts', {
url: '/alerts',
templateUrl: 'alerts.html'
})
.state('newSymptom', {
url: '/newSymptom',
templateUrl: 'newsymptom.html'
})
.state('symptoms', {
url: '/symptoms',
templateUrl: 'symptoms.html'
})
.state('newAlert', {
url: '/newalert',
templateUrl: 'newalert.html'
})
.state('settings', {
url: '/settings',
templateUrl: 'settings.html'
})
.state('location', {
url: '/location',
templateUrl: 'location.html'
});
$urlRouterProvider.otherwise('/');
}).
//some controllers goes here
What I have already checked/tried to do?
I put example content to index.html - it worked.
I tried chanage the name of ui-view and add them in templateURL values of each state.
I changed the .html files to exlude error in them, but it did not helped.
Can anyone more experienced with Ionic/Angular give me a hint what is wrong here?
I seem to notice that it's often due to the modules you're loading in. So It's likely in this line.
angular.module('starter', ['ionic', 'ngStorage', 'ngAnimate', 'naif.base64', 'ui.router'])
Try checking each module by making sure:
You added it to your index.html
it's being called correctly
it's up to date
You can figure out by removing each, one at a time and then seeing if it works on the device.
Also know that AngularJS out of the box uses AngularUI Router and this uses a thing called routing for views. The UI-Router uses a thing called states that is the most used but the unofficial way for AngularJS and Ionic uses their own view state system that is basically the same thing as the UI-Router just with the Ionic namespace. So that is something you need to look up or you may find yourself running into a lot of walls during you builds because you are calling ui.router and I bet it's what's confusing your app, so remove it.
I need to track when a user changes the state of a checkbox in Ionic, save it to localStorage, and then use it to load again later - so it remembers their settings.
My toggle code looks like this:
<li class="item item-toggle">
National Insurance {{ni_toggle}}
<label class="toggle toggle-positive">
<input type="checkbox" ng-model="ni_toggle" ng-click="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
<div class="track">
<div class="handle"></div>
</div>
</label>
</li>
And in my controller I have:
angular.module('starter.controllers', [])
.controller('SettingsCtrl', function($scope, $ionicPlatform) {
$ionicPlatform.ready(function() {
// Ready functions
});
$scope.updateLocalStorage = function() {
window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
console.log( $scope.ni_toggle );
}
})
However, it logs out to the console as undefined. If I explicitly set $scope.ni_toggle = false; it will log false and won't update to true when I toggle the checkbox to on.
EDIT:
app.js:
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', '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(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.settings', {
url: '/settings',
views: {
'tab-settings': {
templateUrl: 'templates/tab-settings.html',
controller: 'SettingsCtrl'
}
}
})
.state('tab.info', {
url: '/info',
views: {
'tab-info': {
templateUrl: 'templates/tab-info.html',
controller: 'InfoCtrl'
}
}
})
.state('tab.about', {
url: '/about',
views: {
'tab-about': {
templateUrl: 'templates/tab-about.html',
controller: 'AboutCtrl'
}
}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
});
controllers.js:
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope) {
})
.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
$ionicPlatform.ready(function() {
});
$scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === "true";
$scope.updateLocalStorage = function() {
$window.localStorage.setItem( 'has_national_insurance', $scope.ni_toggle );
console.log( $scope.ni_toggle );
}
})
.controller('InfoCtrl', function($scope) {
})
.controller('AboutCtrl', function($scope) {
});
templates/tab-settings.html:
<li class="item item-toggle">
National Insurance {{ni_toggle}}
<label class="toggle toggle-positive">
<input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" id="has_national_insurance" name="has_national_insurance">
<div class="track">
<div class="handle"></div>
</div>
</label>
</li>
Working example of the problem
I am not familiar with Ionic's oddities (if there are any), but from a general JS perspective there seem to be a few issues with your code.
You are not initializing ni_toggle.
You are using ngClick which will get fired before the model has been updated by the ngModel directive.
You should use ngChange instead.
In Angular, you should use $window instead of window (it doesn't hurt and it can prove useful in many cases (e.g. testing)).
Note that localStorage can only store strings (not booleans). So, even if you pass false, it will be stored as 'false', which is equivalent to true when cast to boolean.
Taking the above into account, your code should look like this:
<input type="checkbox" ng-model="ni_toggle" ng-change="updateLocalStorage()" ... />
.controller('SettingsCtrl', function($scope, $window, $ionicPlatform) {
$ionicPlatform.ready(function() {
// Ready functions
});
$scope.ni_toggle = $window.localStorage.getItem('has_national_insurance') === 'true';
$scope.updateLocalStorage = function () {
$window.localStorage.setItem('has_national_insurance', $scope.ni_toggle);
console.log($scope.ni_toggle);
};
});
See, also, this short demo.
I ran into a similar situation for displaying user information a while ago with my ionic app. I don't have my original source code in front of me but I'm pretty sure this is how you need to do it.
angular.module('starter.controllers', [])
.controller('SettingsCtrl', function($scope, $ionicPlatform) {
this.toggle = true; // make sure its defined somewhere
$scope.ni_toggle = function() {
return this.toggle;
}
$scope.updateLocalStorage = function() {
window.localStorage.setItem(
'has_national_insureance',
$scope.ni_toggle
);
console.log($scope.ni_toggle);
}
});
Hope this gets you going in the right direction.
EDIT
See ExpertSystem's answer. He answered it way better than I could.
No need of any function definition in controller
<script>
angular.module('checkboxExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.checkboxModel = {
value1 : true,
value2 : 'YES'
};
}]);
<form name="myForm" ng-controller="ExampleController">
<label>Value1:
<input type="checkbox" ng-model="checkboxModel.value1">
</label><br/>
<label>Value2:
<input type="checkbox" ng-model="checkboxModel.value2"
ng-true-value="'YES'" ng-false-value="'NO'">
</label><br/>
<tt>value1 = {{checkboxModel.value1}}</tt><br/>
<tt>value2 = {{checkboxModel.value2}}</tt><br/>