Angular-js $scope variable is not updated in view - angularjs

I am new to angular-js and building a simple to-do application. I am creating a task and displaying the created task in a html table using ng-repeat. But the problem is that after posting the data, $scope.tasks variable is updated on controller side, but not in view. The view updates after refreshing the web page only and the task is added to html table. How can I make the view update after creating the task. Thanks in advance. Here is my code:
In my controller:
var app = angular.module('MyApp', ['ngMaterial', 'ngMessages']);
app.controller('DemoCtrl', function($scope,$mdSidenav,$mdDialog,$interval,$http,$mdToast) {
$scope.tasks = [];
_refreshTaskData(); //initial refresh
$scope.submitForm = function() {
var description = "";
var taskId = "";
$scope.formData = {
taskId: $scope.taskId,
description: $scope.description,
};
$http({
method: "POST",
url: 'savetask',
data: angular.toJson($scope.formData),
headers : {
'Content-Type': 'application/json',
}
}).then(_success, _error);
};
function _refreshTaskData() {
$http({
method : 'GET',
url : 'getTask',
}).then(function(res) { // success
$scope.tasks = res.data;
}, function(res) { // error
console.log("Error: " + res.status + " : " + res.data);
});
}
function _success(res) {
$mdDialog.hide();
console.log('in success function');
_refreshTaskData(); ;
}
function _error(res) {
//error handling
}
});
In my view:
<table>
<tr ng-repeat=" t in tasks">
<td>{{t.id}}</td>
<td>{{t.description}}</td>
</tr>
</table>

You must understand that these JS frameworks are asynchronous. Now what happens is, if you do an API call and make another API call whose result is based on the first one, the console does not wait for the result from one API and directly moves forward. SO what's happening in your case is sometimes/many times, before the POST call is served, the controller is not able to get fresh data with GET in time, thus not updating the view. What you can possibly do is enforce the GET only when POST is served
$http({
method: "POST",
url: 'savetask',
data: angular.toJson($scope.formData),
headers : {
'Content-Type': 'application/json',
}
}).then(function(res){
$http({
method : 'GET',
url : 'getTask',
}).then(function(res) { // success
$scope.tasks = res.data;
}, function(err) { // error
console.log("Error: " + err.status + " : " + err.data);
});
});
It would be best if you are sending a success message from the backend and checking before GET call

I think you are not calling _refreshEmployeeData at any point of time. If you add that instead of _refreshTaskData in your JS, then you will be able to see the result in view.
Also kindly use ng-init to call the _refreshEmployeeData in the controller. That would be the best way to initialize the fields.

Related

Disable form/page until APIs that load controls are complete

I have an HTML form that makes use of a select element. The options of the select element are populated via an API call. I am finding that at times the page appears to be done loading but the select element is not yet populated. I am looking for a way to disable the page or indicate that it is not finished loading until the select element is populated from the API.
I have a single controller that handles the population of the select element as well as the Submit button click event which submits the form data to the back-end API. Below is my Angular and a snippet of the HTML that contais the select element.
HTML
<select ng-model="self.form.UserName"
ng-options="user.Name as user.Name for user in self.userList"
ng-required="true">
<option value="">- Choose User -</option>
</select>
Angular
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.controller('myAppController', function ($scope, $http) {
var self = this;
self.userList= [];
$http({
method: 'GET',
url: 'https://myApi.local/api/users/getAllUsers',
headers : {
'Content-Type': 'application/json'
}
}).then(function(result) {
self.userList= result.data;
}, function (error) {
console.log(error);
});
self.submitFormData = function() {
// form data submission handled here
}
});
</script>
Would this be a good use of ng-cloak to hide the entire page?
I would lay my call out more like this to get the finally block. I would have a spinner on the page show and block the user from touching anything behind it while it was going. This way, the user knows the page is still loading and cannot interact with the unpopulated drop-down.
$scope.showSpinner = true;
$http({
method: 'GET',
url: 'https://myApi.local/api/users/getAllUsers',
headers : {
'Content-Type': 'application/json'
}
}).then(function(result) {
self.userList= result.data;
}).error(function (error) {
console.log(error);
}).finally(function(){
$scope.showSpinner = false;
});

How to post data on button click using AngularJS

I have an application made with .NET core framework and pure html in the front end. I was using AJAX to post and get data.
I am new to Angular and decided to convert the front end of the application to Angular for learning purposes.
For Example, I have a button that will change the state of employees from 'Billed' to 'Available' state. The ID for available state is defined in the back end and it is '1'.
//MOVE TO BENCH BUTTON CLICK
$(document).ready(function()
{
var allVals = [];
$("#MoveToBench").click(function()
{
$('input:checkbox:checked').each(function () {
allVals.push($(this).val());
});
for (i = 0;i<allVals.length;i++){
PostBenchList(allVals[i])
}
function PostBenchList(entityId) {
var data = 'entityID='.concat(entityId).concat('&nextStateId=1');
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://localhost:1783/api/Workflow?"+data,
data: data,
dataType: "text",
success: function (data) {
location.reload();
alert("Successfully added the selected Employees to TalentPool");
},
fail: function (error) {
Console.Log(error);
}
})
}
});
});
The above code is taking an array of entityID's as input. For the Angular application, the array is not required as only one entity ID will be passed.
The API controller in the backend is :
// POST api/values
[HttpPost]
public void Post(int entityId, int nextStateId)
{
JObject jsonObject = JObject.Parse(System.IO.File.ReadAllText("Config.Json"));
string jsonFile = jsonObject.GetValue("WorkfowJsonFileLocation").ToString();
var nextState = _stateServices.Get(nextStateId);
var handler = new WorkflowHandler(nextState, jsonFile, _entityServices, 1, _stateServices, _subStateServices, _appServices);
handler.PerformAction(entityId);
}
The above code worked for me and it would change the state ID of the employee(EntityID)to 1(nextStateId)
Now I have a button in AngularJS and I want it to do the same action. How would I achieve this? As I am still in the procedure of learning, I don't have a clue how to do this. Can anyone help me to achieve this? This would help me to learn and do all similar buttons.
Thank You.
You can use ng-click and call a function to post the data,
HTML:
<button ng-click="PostData()">
Click to POST
</button>
Controller:
app.controller('PostController',['$scope',function($scope)
{
$scope.sendPost = function() {
var data = $.param({
json: JSON.stringify({
name: $scope.newName
})
});
$http.post("/echo/json/", data).success(function(data, status) {
$scope.hello = data;
})
}
}]);
DEMO APP

ng-repeat is not updating my mode data

I am new to angularJS. I am using ionic framework for android application development. In my project I am calling webservice and getting its response and attaching that response to scope variable to get data on the view. First time webservice called and updates the view as expected but when I call the service again that is not updating my data. It seems as ng-repeat is not working due to some reference loosing problem. But I am not able to find out the solution of that. Although I have tried different solution via using apply() as was mentioned in one of the stack overflow posts. Below is the code of attaching web-service response to the scope variable.
$http(req).then(function (response) {
if (response.data.IsSuccess) {
console.log("data = " + JSON.stringify(response.data));
console.log('Response is '+response.data.IsSuccess);
$scope.companies = response.data.Response.Companies;
}
and below is the line of code using to update the view
<div class="col col-100" ng-repeat="company in companies">
any help or advice
Below is the login code that is calling webservice to update my data
function callLogInService(userName, password){
console.log("user name is " +userName);
console.log("password is " + password);
var req = {
method: 'POST',
url: ApiUrl + '/api/User/LoginUser',
headers: {
'Content-Type': 'application/json'
},
data: {
Email: userName,
Password: password
}
}
$ionicLoading.show({
template: 'Signing in...'
});
$http(req).then(function (response) {
if (response.data.IsSuccess) {
console.log("data = " + JSON.stringify(response.data));
console.log('Response is '+response.data.IsSuccess);
var userID = response.data.Response.AppUserId;
var userName = response.data.Response.AppUserName;
setUserName(userName);
setUserId(userID);
$rootScope.appUserName;
var userIdFromSession = getUserID;
if(undefined == $rootScope.companyIdForSubscription
|| $rootScope.companyIdForSubscription == 0){
console.log("id is undefined for subscription");
} else {
console.log("company subscription id is " + $rootScope.companyIdForSubscription);
$scope.subscribe($rootScope.companyIdForSubscription);
}
$scope.close();
$scope.setVisibilityOdSideMenuIcons();
$scope.getAllCompanies();
}
else {
showErrorAlertDialogue(response.data.ErrorMessage);
}
}, function (reason) {
console.log('reason is ' + reason.data);
$log.info('reasonf log is' + reason) ;
showErrorAlertDialogue("Please check your internet connection.");
}).finally(function () {
console.log("finally is called");
$ionicLoading.hide();
$ionicPopup.close()
});
}
$scope.getAllCompanies(); this line is calling service again

AngularJS jsfiddle $http echo not returning data

I encountered a bug in a square-connect API wrapper for node, and I made a fiddle to recreate the issue. I noticed my code wasn't working, in the sense that angular {{}} stuff isn't showing up. What's wrong with it?
the only thing I'm trying to do is have the raw JSON object (preferably {{res}}, but it doesn't matter really) shown below the create button. I am just trying to demonstrate to the author of a library that my object and data is valid, and that a bug is in his library, not my implementation.
var httpRequest = $http({
method: 'POST',
url: '/echo/json/',
data: item
}).success(function(data, status) {
$scope.res = data;
}).failure(function(data, status){
$scope.res = data+status;
});
data is not being returned from jsfiddle's ECHO.
http://jsfiddle.net/efjytg6r/2/
You were close, but since you're saving your $http in a variable, you access the methods within it using that variable. (ie: httpRequest.success / etc)
Also it's .error() not .failure()
var httpRequest = $http({
method: 'POST',
url: '/echo/json/',
data: item
});
httpRequest.success(function(data, status) {
$scope.res = data;
});
httpRequest.error(function(data, status){
$scope.res = data+status;
});
jsFiddle is finicy with it's echo AJAX examples. You need to format what you send to them correctly with json, have it stringified as well as use jQuery's $.param (since angular doesn't do POST like you're used to with jQuery).
I included jQuery to the fiddle below.
I formatted the data being sent differently
I moved your {{ res }} inside of the controller area (you had it outside, which means it won't compute)
I added | json filter to {{ res | json }}
Updated jsFiddle
// the wacky format you need if you want to do fake $http to jsFiddle
// case in point, if you're trying to DEMO this, I wouldn't even bother, since it won't look like this when you actually use this within your application
var data = $.param({
json: JSON.stringify({
item
})
});
$http.post("/echo/json/", data)
.success(function(data, status) {
$scope.res = data;
}).error(function (status) {
});
Here is an example using $httpParamSerializer and a delay.
angular.module('myApp',[]);
angular.module('myApp').controller('myVm',
function($scope,$http,$httpParamSerializer) {
var vm = $scope;
var xitem = {a:"1",b:"2"};
var data = $httpParamSerializer({
json: xitem,
delay: 6
});
console.log("Posting xitem");
vm.p = $http.post('/echo/json/',data);
vm.p.then (function(response) {
console.log(response);
console.log(response.data)
})
});

AngularJS $http ajax request is not asynchronous and causes page to hang

I have a service where I am pulling data from server. When I click the button to send out the request to server through this service, the window freezes until I receive a response from server. Is there anything I can do to make this request asynchronous ?
Here is my service.
app.factory('service', function($http) {
return {
getLogData : function(startTime,endTime){
return $http({
url: baseURL + 'getLogData',
method: 'GET',
async: true,
cache: false,
headers: {'Accept': 'application/json', 'Pragma': 'no-cache'},
params: {'startTime': startTime , 'endTime': endTime}
});
}
};
)};
HTML.
<button ng-click="getData()">Refresh</button>
<img src="pending.gif" ng-show="dataPending" />
Code
$scope.getData = function(){
service.getLogData().success(function(data){
//process data
}).error(function(e){
//show error message
});
}
While there is some argument about the pros and cons of your approach, I am thinking that the problem is answered here: AJAX call freezes browser for a bit while it gets response and executes success
To test if this in fact part of the problem, dummy up a response and serve it statically. I use Fiddler or WireShark to get the response and then save to a file like testService.json. XHR and all of it's various derivatives like $HTTP $.ajax see it as a service though the headers might be slightly different.
Use the success promise, and wrap up the log data in a set of objects that you can attach to a $scope.
So instead of having your service have a blocking method, have it maintain a list of "LogEntries".
// constructor function
var LogEntry = function() {
/*...*/
}
var logEntries = [];
// Non-blocking fetch log data
var getLogData = function() {
return $http({
url : baseURL + 'getLogData',
method : 'GET',
async : true,
cache : false,
headers : { 'Accept' : 'application/json' , 'Pragma':'no-cache'},
params : {'startTime' : startTime , 'endTime' : endTime}
}).success(function(data) {;
// for each log entry in data, populate logEntries
// push(new LogEntry( stuff from data ))...
};
}
Then in your controller, inject your service and reference this service's log data array so Angular will watch it and change the view correctly
$scope.logEntries = mySvc.logEntries;
Then in the HTML, simply do something over logEntries:
<p ng-repeat="logEntry in logEntries">
{{logEntry}}
</p>
use this code to config
$httpProvider.useApplyAsync(true);
var url = //Your URL;
var config = {
async:true
};
var promise= $http.get(url, config);
promise.then(
function (result)
{
return result.data;
},
function (error)
{
return error;
}
);

Resources