angularJS: Function in function - angularjs

Hello I'm new in angularJS. Suitable or not to implement function inside function?
For example like this:-
$scope.loadDistrict = function(id) {
// statement
$scope.loadBasedOnYear = function(y_id) {
console.log(y_id);
// statement
};
};

If you bind method on scope, it's available from view.
From your code
$scope.loadDistrict = function(id) {
// statement
$scope.loadBasedOnYear = function(y_id) {
console.log(y_id);
// statement
};
};
loadBasedOnYear won't available until loadDistrict is called.
It's very bad pattern to follow.

It is possible but without context I don't really know why you would do this, calling $scope.loadBasedOnYear before calling $scope.loadDistrict will result in an error so be careful with such a design pattern.

Yes this is fine.
You should watch out for when the function will be executed outside of angular's cycle. E.g. if you do:
setTimeout(function() { $scope.test = 5; }, 1000);
If you need to do this then you need to wrap the function in $scope.$apply(), or use $timeout.

Related

Browser freezes when use function api in ng-if AngularJS

I use angularjs and I have a problem with ng-if when I use a function that returns true or false in two API, the browser is freezes
self.isShow= function() {
service.getKioskLogByKioskId([stateParams.kioskId], function (data) {
self.kioskLog = data;
service.getKiosk([stateParams.kioskId], function (kiosk) {
self.kiosk = kiosk;
debugger
if (self.kioskLog.isConnected && self.kiosk.isActive)
return true;
else
return false;
});
});
}
and in html
ng-if="self.isShow()"
Angular's ng-if can't be an async, it expects to get true/false in synchronous manner.
Don't forget that EVERY angular directive creates a "watch" that will be invoked as part of angular's dirty check mechanism, If you make a "heavy" operation on it, it will stuck the browser.
Basically there are 2 wrong things in your code, the first one, your isShow is not returning boolean value at all, (it always returns undefined).
The second one, you are probably making an API call inside the service.getKioskLogByKioskId method.
In order to solve both of the issues, you can make the service.getKioskLogByKioskId call inside the constructor of you controller, (if it is a component there is $onInit lifecycle hook for that), then save the async result on the controller, and use it the view.
It should look something like that:
class MyController {
constructor(stateParams) {
this.stateParams = stateParams;
this.isShow = false; // initial value
}
$onInit() {
const self =this;
service.getKiosk([stateParams.kioskId], function (kiosk) {
self.kiosk = kiosk;
debugger
if (self.kioskLog.isConnected && self.kiosk.isActive)
self.isShow = true;
else
self.isShow = false;
});
}
}
// view.html
<div ng-if="$ctrl.isShow"></div>

How to apply watcher on a variable without using $scope?

Is there any way to watch changed value of a variable without using $scope?. My manager told me that we may migrate our code to angular2 which do not have $scope so we have to write the code in the way so that when we migrate it to angular2 it needs minimal changes. So now i want to keep track changes of a variable which we do in angular like :
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
Now i want this to something like
app.controller('auditCtrl',
function($scope, $localStorage) {
var adc = this;
angular.extend(this, {
$state: $state,
count: 0
}
//What i want is something like
abc.$watch('count', function() {
alert('hey, count has changed!');
});
})
No, thats not possible. But ask yourself, what is the variable you want to $watch for? If it is a form field, you can simply use ng-change.
If you can use es2015 Syntax, you can add Getters and Setters on the Controllers Prototype which then triggers an update Function.
Something like this:
let auditCtrl = function () {
const adc = self;
adc.counterItem = null;
// etc.
};
Object.defineProperty(auditCtrl.prototype,
"counterItem", {
get: function () {
return this.counterItem;
},
set: function (newValue) {
this.counterItem = newValue;
// Call method on update
this.onCounterItemChange(this.counterItem);
},
enumerable: true,
configurable: true
});
Or, in my opinion the best approach, use a component architecture for your application. With components, you can use some built-in lifecycle-hooks like $onInit, $onChanges etc. This way, you are also thinking in the angular2 way, since you might want to migrate.

angularjs share variable between functions

Within a controller, I'd like to share data between two functions. For example:
controllers.controller('rightDrawerCtrl', function ($scope, $http) {
$scope.shared_id;
$scope.getId = function () {
// get the id via $http, using a secondary id to retrieve the shared_id
}
$scope.useId = function () {
// use the shared_id to make a different api call
}
});
In this example however, when useId() is called, shared_id is undefined.
I presume this is because useId was 'created' while shared_id was undefined, so hasn't been notified of the new value.
The only way I've found to fix this is by using two controllers: Share data between AngularJS controllers
Is there a better way to do this, using only 1 controller?
$scope.shared_id;
After the above statement the shared_id variable of $scope should be undefined - because you haven't assigned it any value.
Despite this the variable is still accessible inside any scope functions because $scope is global for them. And don't forget that you should access it like $scope.shared_id in all the places.
However if you initialize it in the following manner:
$scope.shared_id = 'no id';
.. it would not return undefined.
You can initialize this variable via ng-init too.
Call userId() function when getId() function get result from $http request.
Looks like I simply had to wrap the variable assignment in $scope.$apply
$scope.$apply(function() {
$scope.shared_id = 1234;
});
You can use like this with this is much easier.
var self = this;
this.shared_id;
$scope.getId = function () {
console.log(self.shared_id) ;
}
$scope.useId = function () {
console.log(self.shared_id) ;
}

How to return a new key onchange location in angularjs

The idea is to always have a new key as soon as you change the page, this is my code but I think I have problem
$scope.newKey =function (){
var key =0;
$rootScope.$on('$locationChangeSuccess', function () {
key++ ;
});
return key;
};
If one of you has already tried $locationChangeSuccess it can help me thank you
Why don't you try using angular's service or factory, so that it includes the Scope variable key which is actually globally available to the entire app/module? i mean this is just my view though
I'm not pretty sure - how exactly you want to use your "newKey", but if you need it on your html, then the valverde93's answer is correct:
$scope.newKey = 0; $rootScope.$on('$locationChangeSuccess', function () { $scope.newKey++; });
And on your html:
{{newKey}}
But if you want to use it on your backend (the js files like a function) - then you get always $scope.newKey = 0, just because you're put your console.log after the incrementation function, and you see only the $scope.newKey = 0;
So if you put your console.log in the function - something like:
$rootScope.$on('$locationChangeSuccess', function () { $scope.newKey++; console.log($scope.newKey);});
then you'll see your proper key.
Or you may to use $watch, to check when the scope is changed and to do somthing:
$scope.$watch('newKey', function(newValue ) {
console.log( newValue );
}
);
Good luck.

how to invoke a method in the scope using $timeout

I'm attempting to use $timeout to invoke one function that I have, but I don't know how to invoke a function that is in the $scope. Let me exemplify
I have this:
$scope.play = function(){
// function implementation
if(condition()){
$timeout(play, 1000);
}
}
it doesn't recognize the play function, I have also tried this
$timeout($scope.play, 1000);
and it also doesn't work. I had to work around it like this:
var play = function(){
$scope.playInner();
}
$scope.playInner = function(){
// function implementation
if(condition()){
$timeout(play, 1000);
}
}
But I'm sure there's a better way to do this, does anyone know how I can do that?
as JB Nizet suggested, $timeout($scope.play, 1000) should work fine.
Example:
function ctrl($scope,$timeout){
$scope.data=0;
$scope.play=function(){
$scope.data++;
$timeout($scope.play,1000);
}
}
Live example: http://jsfiddle.net/choroshin/wF8SZ/

Resources