Not able to fetch scope value in back button method in Ionic - javascript

On same template ionic is unable to get the value in ion-nav-bar directive.
Problem - Whatever the amount I filled in textbox <input type="text" placeholder="70" ng-model="getamt"> in below mentioned code, I am able to get the same value at Getting Amt here: {{getamt}} ie.if I type 56 I am able to get 56 typed like Getting Amt here: 56 BUT I am expecting the same to print at Not updating Amt {{getamt}} but in this case I am not getting any value.
I need to send this value to my previous page..so I am trying to do this stuff.
Let me know how to fix this weird issue with ionic.
<ion-view>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button class="button-clear" ng-click="myGoBack(getamt)">
<i class="icon ion-ios7-arrow-back"></i> Not updating Amt {{getamt}}
</ion-nav-back-button>
</ion-nav-bar>
<ion-content class="has-subheader" padding-bottom="true">
<div class="row">
<div class="col col-30">
<input type="text" placeholder="70" ng-model="getamt">
</div>
<div class="col col-30 item">
Getting Amt here: {{getamt}}
</div>
</div>
</ion-content>
</ion-view>
EDIT -
My controller code -
.controller('mystate2Ctrl', function($scope, $stateParams, $localstorage, $rootScope, $ionicHistory) {
console.log("----- mystate2Ctrl -----");
$scope.myGoBack = function(val){
console.log(val);
$ionicHistory.goBack();
};
$rootScope.$on( "$ionicView.leave", function( scopes, states ) {
if( states.stateName == "app.mystate1" ) {
console.log("In Ionic View blah blah code here");
}
});

The problem you're facing has to do with nested scopes and in particular with the way you use your "model".
The scope is not the model.
I would suggest you to watch this video from Miško Hevery where he talks about the problem you're having. At some point he says something like this:
Whenever you have ng-model there’s gotta be a dot in there somewhere.
If you don’t have a dot, you’re doing it wrong.
Anyway, if you want to fix your problem you should define a model in your controller.
The solution is to create one:
.controller('mystate2Ctrl', function($rootScope, $scope, $state) {
$scope.mymodel = { getamt: 0 };
});
Now you can reference your model in your views using the dot and your view should look something like this:
<ion-view view-title="my-app">
<ion-nav-buttons side="right" class="button-clear" ng-click="myGoBack(mymodel.getamt)">
<i class="icon ion-ios7-arrow-back"></i> Not updating Amt {{mymodel.getamt}}
</ion-nav-buttons>
<ion-content class="has-subheader" padding-bottom="true">
<div class="row">
<div class="col col-30">
<input type="text" placeholder="70" ng-model="mymodel.getamt">
</div>
<div class="col col-30 item">
Getting Amt here: {{mymodel.getamt}}
</div>
</div>
</ion-content>
</ion-view>
If you want to see how it works you can check my plunker.
Probably the best approach is the one John Papa suggests in his Angular guidelines.
If you read carefully the controllerAs View Syntax here he states why you should go for this approach:
Why?: It promotes the use of binding to a "dotted" object in the View
(e.g. customer.name instead of name), which is more contextual, easier
to read, and avoids any reference issues that may occur without
"dotting".
Why?: Helps avoid using $parent calls in Views with nested
controllers.
This is a second plunker with the controllerAs sample.

It seems like because, your Getting Amt here: {{getamt}} and Not updating Amt {{getamt}} in two different directives. So make sure they both can access mystate2Ctrl.
And try to define the variable in the controller itself.
.controller('mystate2Ctrl', function($scope, $stateParams, $localstorage, $rootScope, $ionicHistory) {
$scope.getamt = 0;
// your code
})
HTH

Related

AngularJS - Expression not displaying within HTML

I've gone through other questions, but couldn't find any that dynamically loaded controllers/views the way I am. I still fear this may be a duplicate question, but I have done my due diligence and came up empty. Please point me in the right direction if you're better with search terms.
This is how my app works: My index page loads up RequireJS pointing to a main.js file which outlines the initial includes (app.js, routeResolver, and a data service (unused currently). The routeResolver allows me to dynamically load in my views and respective controllers using code such as below within app.js. (Using a consistent naming convention, passing 'home' loads in home.html and associates it with homeController.js from their respective controllers/views locations.) We do not need to use ng-app='appname' because it’s added at runtime by calling angular.bootstrap() within the app.js file.
//Define routes - controllers will be loaded dynamically
var route = routeResolverProvider.route;
$routeProvider
.when('/', route.resolve('home'))
.when('/createnew', route.resolve('createnew'))
In my controller, I'm loading a variable from sessionStorage. (I have confirmed it is there/available. The test alert displays it correctly.) My problem is it is not displayed on the html page, and the console does not produce any errors. I have confirmed the page is accurately associating itself with the controller because if I remove the expression, I get an error that it is not defined... but despite it containing a value, it still doesn't display. All I get is 'Welcome '.
Controller:
'use strict';
define(['app'], function (app) {
var injectParams = ['$location', '$filter', '$window', '$timeout'];
var homeController = function ($location, $filter, $window, $timeout) {
var userTitle = sessionStorage.getItem('userTitle');
alert(userTitle);
};
homeController.$inject = injectParams;
app.register.controller('homeController', homeController);
});
View:
<div class="container-fluid text-center">
<div class="row content">
<div class="col-sm-2 sidenav">
<p>Placeholder</p>
</div>
<div class="col-sm-8 text-left">
<p>Welcome {{ userTitle }}</p>
</div>
<div class="col-sm-2 sidenav">
<div class="well">
<p>Placeholder</p>
</div>
<div class="well"></div>
</div>
</div>
</div>
I'll gladly share more code, but I didn't want to make this too long and I feel like I'm just missing something silly...
At first glance, I noticed you're making a local variable named userTitle when you want to add that variable to $scope.
Inject $scope into homeController and $scope.userTitle = 'test';. This should get you what you want.

Angular JS expression {{ }} not working

AngularJS expression not updating variable value on view, simply it print as source. Here is my controller code,
controller('loginCtrl', ['$scope', '$state', '$rootScope',
function ($scope, $state, $rootScope) {
$scope.testMessage = "Test Msg from scope";
$rootScope.testMessageRoot = "Test Msg from root scope";
}]);
When I render variables testMessage and testMessageRoot on view using expression it simply print the source code as it is.
<div class="container-fluid" ng-controller="loginCtrl">
<div class="row">
<h1>Account Access</h1>
<h2>{{testMessage}}</h2>
<h6>{{ 5 + 5 }}</h6>
<h2>{{$root.testMessageRoot}}</h2>
</div>
</div>
Same controller works well with ng-bind,
<div class="container-fluid" ng-controller="loginCtrl">
<div class="row">
<h1>Account Access</h1>
<h2><span ng-bind="testMessage"></span></h2>
<h6><span ng-bind=" 5 + 5"></span></h6>
<h2><span ng-bind="$root.testMessageRoot"></span></h2>
</div>
AngularJS v1.3.10 used in my application, I couldn't understand what went wrong, your help appreciated.
Is there any use of $state service you have injected in the controller.
Since"$state" is not a valid angular service, removing this will solve your problem.
Yes, there is some issue with angular expression with express, I used ng-bind instead of expression and working fine.

How to simplify angular-ui-router nested state with many combinations of sub states?

Here is the mock up of my app:
"Left side bar" is for directories, while the "main content" is for files. The files are enumerated from the selected directory ([list mode]).
The "left side bar" is to be reused for 2 other purposes:
display form to create new directory ([create mode])
display form to edit selected directory ([edit mode])
Similarly, the main content could also be in [list mode], [edit mode], and [create mode]. So, in total there would be 3 x 3 possible combinations.
Using ng-switch, this one can be modeled quite easily.
<div class="left-bar">
<div ng-switch on="directory.mode">
<div ng-switch-when="list"></div>
<div ng-switch-when="create"></div>
<div ng-switch-when="edit"></div>
</div>
</div>
<div class="main-content">
<div ng-switch on="files.mode">
<div ng-switch-when="list"></div>
<div ng-switch-when="create"></div>
<div ng-switch-when="edit"></div>
</div>
</div>
However, I wish to model this using angular-ui router. I am new to angular-ui, and the state model I could think of now is something like:
.state('main.folder-list.file-list', views: {'left-sidebar':{templateUrl:'directory-list.html'}, 'main-content':{templateUrl:'file-list.html'}})
.state('main.folder-list.file-edit', ...)
.state('main.folder-list.file-create', ...)
.state('main.folder-edit.file-list', ...)
.state('main.folder-edit.file-edit', ...)
.state('main.folder-edit.file-create', ...)
.state('main.folder-create.file-list', ...)
.state('main.folder-create.file-edit', ...)
.state('main.folder-create.file-create', ...)
One important requirement: when the mode of "left side bar" is switched, the content of "main content" shouldn't be changed (it should still be in the same mode as before), and vice versa.
How to simplify that?
First think first, remember that angular-ui router able to handle nested state. I usually use .state('root'), .state('root.app'), .state('root.app.specific'), etc. With that characteristics of angular-ui router, we can simply set $scope at root state like $scope.data = { status: 'ok' } and in root's child, we still able to call that $scope.data.
Also if your create, list, edit is a generic "class" or singleton. You can also make it simple using angular controller inheritance in your controller type $controller('[parent-controller]', {$scope: $scope});. So your parent-controller's $scope like method that they have etc. will be able to called inside your new controller's $scope. Angular-ui router's nested state is similar to this. For example:
Application.controller('AppCtrl', ['$scope', '$controller', function($scope, $controller) {
$controller('AdminCtrl', {$scope: $scope});
}]);
In that example my AppCtrl will have the AdminCtrl's $scope.

Scope of ngController doesn't update with ngInclude

Here is a Plunker: http://plnkr.co/edit/F6QM4KUU8DPNq6muInGS?p=preview
Including an html file with ng-include, having set the ng-controller in the same tag, doesn't update the controller's scope models. Using the ng-model directly inside of the html works perfectly fine, and also setting the controller inside of the included html file is working. But ng-include together with ng-controller $scope.models don't update and stay as they are.
For whatever reason if you set the model inside of the controller, it is done suring it's loading. But having a method setting the model (not included in the plunker) only changes the mdoel inside of the controller's scope and not the html one.
Also if I use an ng-include in the scope of another controller and want to access the included models return undefined or the value you set the model to. Calling methods from the included html works fine in both cases, but they can't really operate as the values are wrong.
I saw that a similar issue has already been postet and should have been resolved (https://github.com/angular/angular.js/issues/4431), but as you can see in the plunker for me it doesn't.
Do I miss something, or is this a problem of angular?
Kind Regards,
BH16
PS: Here is the code from the Plunker:
index.html - body
<body ng:controller="MainCtrl">
<input type="text" ng:model="input">{{input}} {{getInput()}}
<div ng:include="'main2.html'" ng:controller="Main2Ctrl"></div>
</body>
main2.html
<div>
<input type="text" ng:model="input2">{{input2}} {{getInput2()}}
</div>
script.js
angular.module('testApp', [])
.controller('Main2Ctrl', function($scope) {
$scope.input2 = 1234;
$scope.getInput2 = function() {
console.log("input2");
return $scope.input2;
};
})
.controller('MainCtrl', function($scope) {
$scope.input = 1234;
$scope.getInput = function() {
console.log("input");
return $scope.input;
}
});
For all of those who are are also having this issue: Just use the controllerAs syntax: http://toddmotto.com/digging-into-angulars-controller-as-syntax/
This solves all of the issues above and simplifies the code A LOT!
This is the basic idea of controllerAs (taken from the site above):
<div ng-controller="MainCtrl as main">
{{ main.title }}
<div ng-controller="AnotherCtrl as another">
Scope title: {{ another.title }}
Parent title: {{ main.title }}
<div ng-controller="YetAnotherCtrl as yet">
Scope title: {{ yet.title }}
Parent title: {{ another.title }}
Parent parent title: {{ main.title }}
</div>
</div>
</div>
It's related to that ng-include creates it's own scope.
To see what's actually happens you can try plugin(for google chrome, probably something similar exists for others browser's too): "AngularJS Batarang", it will include additional tab to dev tools.
And possible solution will be:
main2.html:
<div ng:controller="Main2Ctrl">
<input type="text" ng:model="input2"> {{input2}} {{getInput2()}}
</div>
http://plnkr.co/edit/daIehNjxWdam3NyH3ww4?p=preview

AngularJS reusing the same controller on one page, with different configuration

I want to display two elements on a page controlled by different instances of the same controller, but I need to register some external information that will be unique (one "joystick" gets an identifying property set, like "player = one" while the other gets "player = two").I'm not sure of the best way of pulling this off exactly
Here's a generic example of what I'm trying to accomplish:
<!-- These need to have different configurations -->
<div ng-include src="'joystick/joy.tpl.html'"
ng-controller="JoystickCtrl">...</div>
<div ng-include src="'joystick/joy.tpl.html'"
ng-controller="JoystickCtrl">...</div>
Should I:
Use a directive?
<div ng-include src="'joystick/joy.tpl.html'"
ng-controller="JoystickCtrl" player="one">...</div>
<div ng-include src="'joystick/joy.tpl.html'"
ng-controller="JoystickCtrl" player="two">...</div>
Use $injector? (fyi - this might be an incorrect implementation)
<div ng-controller="DualJoyCtrl">
<div ng-include src="'joystick/joy.tpl.html'"
ng-controller="joyOne" player="one">...</div>
<div ng-include src="'joystick/joy.tpl.html'"
ng-controller="joyTwo" player="two">...</div>
</div>
-----
.controller('DualJoyCtrl', function ($injector, JoystickCtrl, $scope, $rootScope) {
$scope.joyOne = $injector.instantiate(JoystickCtrl, {$scope: $rootScope.$new(), player:"one"});
$scope.joyTwo = $injector.instantiate(JoystickCtrl, {$scope: $rootScope.$new(), player:"two"});
});
Or... not do this?
I realize this is similar to another, seemingly inconclusive stack post:
Edit
Since ngController is initialized before ngInit, in order to have data available in controller at once, you should wrap ngController in parent element with ngInit:
<div ng-init="player = 'one'">
<div ng-controller="JoystickCtrl">
...
</div>
</div>
Original answer
I think simple ng-init would suffice:
<div ng-controller="JoystickCtrl" ng-init="player='one'">...</div>
<div ng-controller="JoystickCtrl" ng-init="player='two'">...</div>
Store your config values in a data attribute, and retrieve it within the controller using $attrs. (The AngularJS ngInit documentation recommends to say clear of ng-init unless aliasing special properties of ngRepeat. ) A similar answer is here. This code snippet gives you the general idea:
Index.html:
<div ng-include ng-controller="JoystickCtrl" src="'same.html'" data-id="1"></div>
<div ng-include ng-controller="JoystickCtrl" src="'same.html'" data-id="2"></div>
Controller:
function joystickCtrl($scope, $attrs) {
$scope.id = $attrs.id;
};
View:
<h2>Joystick: {{id}}</h2>
Here is the full code in Plunker.

Categories

Resources