So I have a service like that:
.service("checkSystemStatus", ["$http", "statusUrl", function($http, statusUrl){
return $http({method: "GET", url: statusUrl, cache: false});
}])
With this markup:
<li ng-mouseenter="checkStatus()">
<i class="fa fa-info-circle"></i>
<div class="info-container">
<h4>System Info</h4>
<table class="system-info">
<tr ng-repeat="(key, value) in systemInfo">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>
</li>
and this function:
$scope.checkStatus = function(){
$scope.systemInfo = {};
checkSystemStatus.then(function(success){
$scope.systemInfo.running = success.data.jobs_running;
$scope.systemInfo.queued = success.data.jobs_queued;
$scope.systemInfo.cached = success.data.jobs_cached;
$scope.systemInfo.active_threads = success.data.threads_active;
$scope.systemInfo.server_address = success.data.server_address;
$scope.systemInfo.server_port = success.data.server_port;
console.log($scope.systemInfo);
})
}
The issue is I always get the same values for systemInfo, anytime I hover the info icon, I can't see any XHR requrest in the console except for the first one, that happens on loading the page and NOT when I hover the mouse on the tag.
The only way to solve this so far has been adding a parameter at the end of the url like
?time=unixtime to get a new url each time, but what about a cleaner solution without trailing params? Is it possible?
Well, it not only depends on the "AngularJS"-Cache but also on the Browser and Server cache settings. Check what kind of Cache-Headers the server in his responses sends to the Client. Adding a "timestamp" parameter to the REST-URL is one trick to avoid browser based caching - yes.
But in general: That's the way a client-server communication is intended to be. I would suspect that the Server sends some Vary, ETag, Cache-Expire etc. headers which will match.
Try to add these http headers into the server's response:
Cache-Control:no-cache, no-store, must-revalidate
Expires:-1
Pragma:no-cache
Try like this
.service("checkSystemStatus", ["$http", "statusUrl", '$q', function($http, statusUrl, $q){
this.GetData = function(){
$http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
return $http({
method: "GET",
url: statusUrl,
cache: false //no need to use this, caching is false by default
}).
then( function(response){
if (response.data) {
return response.data;
}
else
return $q.reject('Request failed');
});
}
}]);
Controller part
$scope.checkStatus = function(){
$scope.systemInfo = {};
checkSystemStatus.GetData().then(function(data){
$scope.systemInfo.running = data.jobs_running;
$scope.systemInfo.queued = data.jobs_queued;
$scope.systemInfo.cached = data.jobs_cached;
$scope.systemInfo.active_threads = data.threads_active;
$scope.systemInfo.server_address = data.server_address;
$scope.systemInfo.server_port = data.server_port;
console.log($scope.systemInfo);
})
}
As other answers tell you: the browser may choose to cache the response if the appropriate response headers from the server is not set. Set the response headers in MajoBs answer.
If you are unable to update the response headers from the server you could make sure that the url is unique for every request. You can do this by adding a timestamp to the url:
.service("checkSystemStatus", ["$http", "statusUrl", function($http, statusUrl){
statusUrl = statusUrl + '?' + Date.now();
return $http({method: "GET", url: statusUrl, cache: false});
}])
Related
When I try to change the status of a blog , the status is not updating in database. Status is string field and is initially stored as 0 in database
api.post('/statuschange', function(req, res){
Blog.find({_id: req.query.blog_id}).update({$set:{'status': req.body.status}}, function (err, status) {
if(err){
res.send(err);
return;
}
if(req.body.status == '1') {
res.json('Blog added')
return;
}
if(req.body.status == '-1'){
res.json('Blog not added');
return;
}
});
})
api is working successfully on postman
factory file
angular.module('blogfact', ['authService'])
.factory('blogFactory', function($http, AuthToken){
var factory = {};
var token = AuthToken.getToken();
factory.changestatus = function(info, callback){
$http({
url: 'api/statuschange',
method:'POST',
headers:{'x-access-token':token},
params:{'blog_id': info},
})
.success(function(response){
callback(response)
})
}
return factory
})
the controller file
angular.module('blogCtrl', ['blogfact']);
.controller('BlogController', function(blogFactory, $routeParams){
var that=this;
blogid = $routeParams.id;
var getthatBlog = function(){
blogFactory.getthatBlog(blogid, function(data){
//console.log('[CONTROLLER] That Blog:',data);
that.blog = data;
})
}
this.changestatus = function(info){
blogFactory.changestatus(info, function(data){
getthatBlog();
})
}
})
html file
<div ng-controller="BlogController as blog">
<textarea ng-model="blog.status"></textarea>
<button class="btn btn-success" ng-click="blog.changestatus(blog._id)">Submit</button>
</div>
If your question is regarding the value in MongoDB not being updated, well it seams it is due to the status data missing in your POST request.
I recommend that in your HTML, send the whole blog object so that you have the blog's status as well:
<button class="btn btn-success" ng-click="blog.changestatus(blog)">Submit</button>
Then in your blogFactory add the data as such:
$http({
url: 'api/statuschange',
method:'POST',
headers:{'x-access-token':token},
params:{'blog_id': info._id},
data: {status: info.status} // <==
})
Now, you should be able get the blog status data in NodeJS server back-end via req.body.status.
Update
Try the following with mongoose's update method:
Blog.update({_id: req.query.blog_id}, {status: req.body.status}, function(err, numAffected){
...
});
Or, alternatively:
Blog.findOne({_id: req.query.blog_id}, function(err, blog){
blog.status = req.body.status;
blog.save();
});
Angular let's you modify collection data on the client-side, but to actually update it on your server you need to notify the server of your changes (via API).
There are a few ways to do this, but if you want seamless updating from client-side to server maybe give meteor a try.
http://www.angular-meteor.com/
https://www.meteor.com/
Your are sending the data in params and getting the data from req.body.
You should use req.query or req.param. Else, Send the data on body like below,
$http({
url: 'api/statuschange',
method: 'POST',
params: { 'blog_id': info },
data: { 'status': 1 }
})
Your are passing 1 parameter in client side and getting two parameters on server side(req.body.status, req.query.blog_id)
Where is the token value from ?
Check the simplified way to test your code
http://plnkr.co/edit/tyFDpXw2i0poICwt0ce0
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)
})
});
I am trying to get dynamic data from the json according to $http results, but it doesn't work for me. I think that the problem is with the callback. I mean that is the code run to json results when my $http continue to run.
This is my javascript code:
var operation_types = operation_types = [
{nav_id: 1, nav_name: "Validation", nav_src: "validation", nav_href: "validation_list"},
{nav_id: 2, nav_name: "Guests", nav_src: "guests", nav_href: "guests_list"}
];
angular.module("mainApp", ["kendo.directives"])
.controller("HomepageCtrl", function ($scope,$http) {//Homepage
/*receive user properties*/
$http({
url: 'API/v1/User/GetUserInfo',
method: "GET",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
if (data.Code != 1) {
$scope.error = "Please enter valid username and password!";
} else {
console.log(data);
if(data.viewGuest==true&&data.viewValidation==true){
$scope.source =operation_types;
}else if(data.viewGuest==false){
source = operation_types[0];
}else if(data.viewValidation==false){
source = operation_types[1];
}
//window.location.href = "homepage.html";
}
}).error(function (data, status, headers, config) {
$scope.error = "There are problems with connection to server. Status:" + status + " Please, try to connect later.";
$scope.validationClass = "invalid";
});
$scope.source =operation_types;
})
This is the relevant snippet of my html code (with kendo ui):
<kendo-mobile-list-view k-data-source="source">
<div class="product" k-template>
<a href="\#{{dataItem.nav_href}}">
<img src="images/{{dataItem.nav_src}}.jpg" alt="{{dataItem.nav_name}} image" class="pullImage"/>
<h3>{{dataItem.nav_name}}</h3>
</a>
</div>
</kendo-mobile-list-view>
Does somebody know how to do it in angular?
Some general things to consider :
Your code is not using only vanilla angular , but also a 3rd party
library of client side controls (Telerik Kando)
Does the binding work if data is set to the sources json directly ?
Please see for example of kendo-mobile-list-view usage at http://demos.telerik.com/kendo-ui/mobile-listview/angular
Are you sure you the ajax request gets to the server ?
Are you sure the JSON returned is what you expect (use network
monitor in the dev tools in your browser of choice to find out , F12
usualy )?
Edit
Also
At
if(data.viewGuest==true&&data.viewValidation==true){
$scope.source =operation_types;
}else if(data.viewGuest==false){
source = operation_types[0];
}else if(data.viewValidation==false){
source = operation_types[1];
}
Sometimes you set the source on the $scope
$scope.source =operation_types;
and other you set a local variable named source.
source = operation_types[1];
Did you mean to set the
$scope.source
At the 2 last 'if' branches?
Another thing:
$http call is asynchrounus . So if you ment to assign initial value to
$scope.source
then it is better done before the ajax call , otherwise you risk a race condition.
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;
}
);
I am new at AngularJS and I needed your help.
All I need just need is to POST my json to the API and recieve the proper response.
Here's my JSON where i don't know where to code this.
JSON
{
"userId" :"testAgent2",
"token" :"testAgent2",
"terminalInfo":"test2",
"forceLogin" :"false"
}
NOT SURE IF I'm doing this right.
CONTROLLER.JS
function UserLoginCtrl($scope, UserLoginResource) {
//Save a new userLogin
$scope.loginUser = function() {
var loggedin = false;
var uUsername = $scope.userUsername;
var uPassword = $scope.userPassword;
var uforcelogin = 'true';
UserLoginResource.save();
}
}
SERVICES.JS
angular.module('UserLoginModule', ['ngResource'])
.factory('UserLoginResource', function($resource, $http) {
$http.defaults.useXDomain = true;
delete $http.defaults.headers.common['X-Requested-With'];
$http.defaults.headers.post["Content-Type"] = "application/json"; //NOT WORKING
return $resource('http://123.123.123.123\\:1234/SOME/LOCATION/THERE', {}, {
save: {
method:'POST',
headers: [{'Content-Type': 'application/json'}]
} //NOT WORKING EITHER
});
});
INDEX.HTML
<html ng-app>
<head>
<script src="js/lib/angular/angular.js"></script>
<script src="js/lib/angular/angular-resource.js"></script>
</head>
<body ng-controller="UserLoginCtrl">
<form class="form-horizontal" name="form-horizontal" ng-submit="loginUser();">
<div class="button-login">
<!-- start: button-login -->
<button class="btn btn-primary" type="submit">Login</button>
</div>
</form>
</body>
</html>
I kept on getting a response like Unsupported Media Type. I don't know, what else to do.
Assuming you are able to use one of the more recent "unstable" releases, the correct syntax to change the header is.
app.factory('BarService', function ($resource) {
var BarService = $resource('/foo/api/bars/:id', {}, {
'delete': {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
}
});
return BarService;
});
I find the $resource service is a tremendously powerful tool for building applications and has matured to a point that you do not need to fall back to $http as much. Plus its active record like patterns are damn convenient.
Posting a JSON object is quite easy in Angular. All you need to do is the following:
Create a Javascript Object
I'll use your exact properties from your code.
var postObject = new Object();
postObject.userId = "testAgent2";
postObject.token = "testAgent2";
postObject.terminalInfo = "test2";
postObject.forceLogin = "false";
Post the object to the API
To post an object to an API you merely need a simple $http.post function. See below:
$http.post("/path/to/api/", postObject).success(function(data){
//Callback function here.
//"data" is the response from the server.
});
Since JSON is the default method of posting to an API, there's no need to reset that. See this link on $http shortcuts for more information.
With regards to your code specifically, try changing your save method to include this simple post method.
The right way to set 'Content-Type': 'application/json' is setting a transformRequest function for the save action.
angular.module('NoteWrangler')
.factory('NoteNgResource', function NoteNgResourceFactory($resource) {
// https://docs.angularjs.org/api/ngResource/service/$resource
return $resource("./php/notes/:id", {}, {
save : { // redefine save action defaults
method : 'POST',
url : "./php/notes", // I dont want the id in the url
transformRequest: function(data, headers){
console.log(headers);
headers = angular.extend({}, headers, {'Content-Type': 'application/json'});
console.log(headers);
console.log(data);
console.log(angular.toJson(data));
return angular.toJson(data); // this will go in the body request
}
}
});
});
It seems there isn't a method to clear query parameters, the request will have both...