Why $http in ng-init is not getting called everytime the view is loaded - AngularJS - angularjs

I have modified my question as per my observation.$http request on server side is not happening whenever the view is called second or third or so on times although initWishList (ng-init) is getting called. The scenario is as below:
I have a My Account tab in the nav-bar, which opens a view having options like MyWishlist, My Address etc. When My wishlist is clicked for the first time, $http request happens, but when I again click on My Account (this time I don't see any call on server side when the .html view is loaded) , and then if I click My Wishlist , the controller is called but $http isn't called (this time I again dont see any call on server side from $http) but I can see the alert Init Called
Why so?
$scope.initWishList = function(){
alert('Init called')
$http.get("/get_wish_list/")
.success(function (response) {
$scope.refreshWishList(JSON.parse(response["products_json"]));
})
.error(function(){
console.log('Error');
});
};
Hope I have explained the scenario properly.

Controllers gets intialized only once when angular parses ng-controller directive. Since controller is initialized once, ng-init will also run once.
For your satisfaction, add a break point in the your controller on the first line, see when you hit that break point. Are you hitting that break point, every time you click the tab ? If not, ng-init will not be called every time

Related

communicating between two controller in angularjs using factory

I have created a plunker that communicates between two different controller in nested views using factory. Below is the url of plunker.
https://plnkr.co/edit/fWA2Xugjbkf3QvHKfTa0?p=preview .
Here is the factory.
routerApp.factory("widgetService",function($state){
var callbackFunctions=[];
var counter=0;
var addWidget=function(name){
callbackFunctions[0](name);
}
var addCallback=function(callback){
if (callbackFunctions.length===0) {
callbackFunctions.push(callback);
}
}
return{
addCallback: addCallback,
addWidget: addWidget
}
})
Scenario 1:
1. Click on "List" menu under the home page.
2. Click on "verify" button. notice the change in highlighted area with yellow. Text changes from "Chandan" to "singh1".
3. Click again on verify button. Text changes from "singh1" to "singh2". So i am able to communicate between two controller in this.
Scenario 2:
1. Repeat the scenario 1 till step 2.
2. Click on "PARAGRAPH" menu under home page.
3. Click on "List" menu under home page. Click verify button. The text wont change. It will remain "chandan".
Communication is not working as we change the state.
Also i have observed that the model is changing but same is not getting reflected in view. Moreover if we bind the view to rootscope, view is getting updated.
Please clarify.
When you switch between list and paragraph states, your list controller is destroyed (and recreated next time you go to list). So when it is recreated it gets a new scope.
The callbackFunction that is registered in your service, refers to the changeMyName() function on the old controller scope, so whenever you call addWidget() in your service, you're actually calling the callback in your old scope.
To make this work as expected (at least in your sample code here), you would have to change your service to allow changing the old callback in the addCallback()-function. Something like this:
var addCallback=function(callback){
callbackFunctions[0] = callback;
}

Pass service result to other controller

I am calling getLanguageSpecificData(LangCode) service from home controller and saving the data into localStorage. On Home page there are Language links, if user click on English then it will redirect to a second template. But the problem is that still home controller getLanguageSpecificData(LangCode) service is not completed its execution.So in second Controller when I am trying to get result from localStorage it is incorrect(not updated).
So can you please tell which is better approach in this situation ?
HomeController code :
app.controller('homeController',function($scope,$localStorage,$appService){
$scope.loadlanguagefile = function(langcode){
$troubleshootingService.getLanguageSpecificData(LangCode).then(function(responce){
$localStorage.data = responce.data;
});
}
});
'loadlanguagefile' function is called when user click on Enlgish link and app is redirect to second template. here is secondController code :
app.controller('secondController',function($scope,$localStorage){
$scope.data = $localStorage.data;
});
As per my suggestion, you should use callback function to do your need full, when the function is called make the English click disable , and if your result is successful the make that enable. It will be something like this:
getLanguageSpecificData(LangCode,callback:(dataToReturn:any)=>void):any{
//logic here to get data to return
callback(dataToReturn);
}
For calling this method -
1- before calling the method make English click disable.
2- then call the method-
getLanguageSpecificData(imputLangCode,(result)=>{
//logic for data modification
//logic to enable English click
});
3- Enable the English click inside the call of the method.

Run a function only the first time when AngularJS gets loaded

I'm using angular-seed template (AngularJS) and I have routeProvider setup and such, now I want to execute a function (which resides in a factory), but only the very first time when the page gets loaded. I found many solutions for this, but I don't want to execute the code each time the users switches between tabs (via routeProvider of course, page doesn't get reloaded) - the code must be executed only when the whole page gets (re)loaded.
How should I approach this? I tried to call the function from run and then broadcast the event when page gets loaded, but there are no event listeners - I guess that is because the run part gets executed before the controllers are setup, so there are no listeners attached at the time when the event gets broadcast.
So, any suggestions how to approach this?
UPDATE
Use case:
when user types the url in the page, the page gets loaded
when pages gets loaded, a $http.get request is performed, which gets a random content
this content can be changed only by clicking a button, to explicitly request a change of content.
if users clicks to a different page e.g. view2 (routeProvider) and then back to the view1, the content must not change
when users refreshes the page (F5), the content changes again (or as already stated, by a click of a button)
Use the run method:
app.run(function(yourService){
yourService.cacheRandomContent();
});
It runs only once after the app is bootstrapped and services are created.
To access the data in controller, just inject the same service:
app.controller('someCtrl',function($scope, yourService){
yourService.getCachedRandomContent().then(function(resp){
$scope.data = resp.data;
});
});
Your service would be something like:
app.service('yourService',function($http){
var promise;
return {
cacheRandomContent: function(){
promise = $http.get();
},
getCachedRandomContent : function(){
return promise;
}
}
});

AngularJS and Ionic click to repeat a failed http request

I'm making an app using AngularJS and Ionic.
When my app sends a request to the server using $http and fails, I want a view to load to show the user a button which, when clicked, repeats the $http request that was just attempted.
Currently if the request fails, it will load an error view, but I want that error view to have a button which performs a repeated task when clicked. This will be the same error controller for all server errors, so needs to be adaptable and have a way to pass in or repeat all functions easily in one place.
function getData(){
$http({
url: remoteUrl+'/dat/get_data_app',
method: 'POST',
data: {}
}).then(function(response) {
}, function(response) {
//the getData is trying to pass in the current function so it can be repeated in the error controller
$localstorage.setObject('httpObj', getData());
$state.go('app.error');
});
}
Below is the error controller currently:
.controller('ErrorCtrl', function($scope, $localstorage, $recipes) {
var httpObj = $localstorage.getObject('httpObj');
//this needs to run as a funtion (only when button is clicked but I can sort that out, just need a way of passing the function here)
httpObj;
})
The error controller runs when the user lands on the error page. In order to make the controller short and not need much changing later, I want the function passed here to run on click of a button which I'll place here.
Adding the button isn't the problem, but I just want to know if there's an easy way to pass the function.
This whole way of doing it may be wrong but any thoughts will be appreciated :)
Thanks

How to use $resource in AngularJS properly for building a client app?

I've been following this tutorial http://draptik.github.io/blog/2013/07/28/restful-crud-with-angularjs/. I implemented a Grails backend with it instead of the Java one in the tutorial.
I've got the data coming back and forth, with one issue. If I create/update/delete a user, I don't see the changes reflected on my user list when I am redirected back. I have to refresh the page to see the updates.
Looking at the network traffic for an edit, it looks like it does a PUT and fires off the GET before the PUT is complete. Assuming this is because $resource returns a promise so things can be done asynchronously. So how do I handle this so that when $location redirects me, my list is up to date?
I'm guessing the options are to wait for the PUT to complete before redirecting/querying for the list, or to somehow manually manage the $scope.users to match the request?
Or maybe this tutorial is just a bad example? Maybe there is a better way to do it (still using $resource)?
Note: I've seen Restangular out there, and I've seen $http with success callbacks, but I would like to understand the situation above.
One way to overcome this issue would be to not redirect to the list page, till you get a callback, and then do a redirect. You can show some busy indicator till that time. The resource call looks like this.
resource.update(config,data,function() { //gets called on success},
function(error) { //gets called on failure});
In real life scenario waiting for the response of update makes sense as you want to handle the error and success scenarios on the same page.
I don't see your code anywhere so i'm just assuming (based on what you wrote and your current problem)
You are probably doing a full (or partial) get each time you changed a user and (re)binding the result to your scope. Doing this in the callback of the resource should actually start the digest cycle angular does to update modified objects. If you had been doing the fetching outside $resource - for example with custom/jquery ajax you would need to execute $scope.$apply()
What i really don't understand you would need to wait for the callback. You already know you added/modified a user. Instead of 'detaching' that user from your scope, modify it, post it to your rest server, then wait for callback, and reinserting it into the scope - why not modify it directly in the list/array you put on your scope?
var users = Users.get(function () {
$scope.users = users.record; // bind the resulting records to the scope
});
$scope.updateUser = function (user) {
resource.update(...); //pseudo
};
Then in your html, you will keep a reference to the currentUser and the div-list will update automaticly.
<div ng-repeat="user in users" ng-click="currentUser=user">{{user.Name}}</div>
<input ng-model="currentUser.Name">
<button ng-click="updateUser(currentUser);">Update</button>
If you don't want to see the update in the list while you type, but only once your callback fires or when you hit the button, would would instead use another ng-model for your input like this:
<input ng-model="tempUser.Name">
And you would then copy the value other in either the updateUser method or in the resource callback like this:
$scope.updateUser = function (user) {
user.Name = $scope.tempUser.Name; // should update automaticly
resource.update(...) // pseudo
}
Hope it helped!

Resources