I am trying to build a sample app that will grab data using JSONP to populate. I have it put up at http://angular.onagrag.com/ and clicking on register.
The file I am trying to load is at http://api.onagrag.com/data.json
When I access http://angular.onagrag.com/register it fires the error method of the object (and it fires it twice)
here is the angular js file that I am using (it is also located at http://angular.onagrag.com/js/test.js
It runs fine if I use local data (e.g. use the $http.get method instead of the $http.jsonp method), but will not work with jsonp. Any help is appreciated!
var App = angular.module('popdust', ['ngResource']).config(['$locationProvider', function($location) {
$location.html5Mode(true).hashPrefix('!')
}]);
App.config(['$routeProvider', function($routes) {
$routes.when('/register',{
templateUrl : '/templates/register.html',
controller : RegisterCtrl
});
$routes.when('/',{
templateUrl : '/templates/home.html',
controller : HomeCtrl
});
}]);
var HomeCtrl = function($scope, $http, $location) {
$scope.title = 'We are home';
$scope.obj = ['one', 'two','three'];
};
var RegisterCtrl = function($scope, $http, $location) {
$scope.title = 'Register!';
$scope.handleData = function(data){
$scope.fields = data;
}
$scope.fetchjsonp = function(){
$http.jsonp('http://api.onagrag.com/data.json?callback=JSON_CALLBACK').success(function(data){
alert("success");
}).error(function(data, status, headers, config) {
alert("YOU FAIL");
});
}
$scope.fetch = function(){
$http.get('js/data.json').success($scope.handleData);
}
$scope.fetchjsonp();
};
HomeCtrl.$inject = ['$scope','$http','$location'];
RegisterCtrl.$inject = ['$scope','$http','$location'];
Looks to me like the problem is with your resource. When I check http://api.onagrag.com/data.json?callback=JSON_CALLBACK I get the following response:
[{
"id" : "first_name",
"title" : "First Name",
"description" : "The name your parents gave you"
},{
"id" : "last_name",
"title" : "Last Name",
"description" : "In Spanish, it's called your apellido (or something like that)"
}]
This is not a valid JSONP response. With the request parameter callback=nameOfCallbackFn the response should be a single function call to a function named nameOfCallbackFn (with the result as it's only parameter).
Update: The server that serves the JSONP must read the callback request parameter and respond with a file that does a method call to the request method name. When you use the angular $http.jsonp method, angular will change the callback request parameter to the correct angular jsonp callback method name (atm they seem to be named angular.callback._0, ..._1 etc). You can't serve a static file as this name might change from one request to the other. This was not clear in my original answer.
Something like this:
nameOfCallbackFn ( [{
"id" : "first_name",
"title" : "First Name",
"description" : "The name your parents gave you"
},{
"id" : "last_name",
"title" : "Last Name",
"description" : "In Spanish, it's called your apellido (or something like that)"
}] );
Where nameOfCallbackFn is specified by angular.
JSONP has some potential security vulnerabilities - you can read more about them and how to prevent them in your angular app here.
Related
Please give me some example of $http.post. I am new in AngularJS. I want to update a JSON file while retrieving information from user. I want to update values but unable to update a JSON file.
My JSON file is data.json.
{ var app=angular.module("APP",[]);
app.controller("APPController", function ($scope, $http){
$scope.add = function(){
var dataObj={ model:$scope.addModel,
car: [$scope.option1, $scope.option2, $scope.option3, $scope.option4],
type: $scope.Type};
$http.post("data.json",dataObj)
.success(function(res){console.log("success"+res.records)}) .error(function(res){console.log("error")});
};
});
}
and here is my data.json file
{
"records": [
{
"model" : "car model",
"car" : ["num1","num2","num3","num4"],
"type" : "mode type"
},
{
"model" : "car model",
"car" : ["num1","num2","num3","num4"],
"type" : "mode type"
},
]
}
You can pass the data object in 2nd param of the $http.post() method.
I am confused to get the exact context of update JSON. But if you want to update the existing variable array in your controller which you are using in view from the response, you can do it it JavaScript way.
Here is a working example for the same. This might help.
JSFiddle: http://jsfiddle.net/ashishanexpert/zvcx5z38/2/
You don't POST data on a JSON file, you make the POST API call to a server.
You can GET data from a JSON file.
I suggest you read through Angular's POST documentation first.
this is the $resource configuration.
'use strict';
angular.module('MyApp')
.factory('Doc',['$resource',function DocFactory($resource){
return $resource('/db/doc/:dbName/:docId/:docRev',
null,
{'upDate': { method:'PUT' }}
);
}]);
DELETE and GET work fine
the upDate function is called with a submit button
$scope.upDate = function(){
Doc.upDate({dbName: 'lol-sched-teams',
docId: $scope.team._id,
docRev: $scope.team._rev})
.$promise.then(function (data) {
$scope.team = data;
});
}
When I debug into angular I find that the '/db/doc/' portion of the url is working fine but the ':docId/:docRev' are not being parsed to build out the entire url.
So at the Express server the request comes in as 'req: PUT /db/doc'
?????
Obviously I am missing SOMETHING!
Any help appreciated
Problem Solved???? Well understood anyway.
This is really not well documented. Happily the angular code is beautifully written and easy to follow.
$resource REALLY WANTS 4 arguments
params, data, function success(){}, function error(){}
If you debug into angular you will see this is the case on the parse of the command args
So I made the PUT work by re-coding the call to the resource factory to be:
Doc.upDate({dbName: 'lol-sched-teams',
docId: $scope.team._id,
docRev: $scope.team._rev},
$scope.team,
function success(data){
console.log(data);
},
function error(err){
console.log(err);
}
)
Within angular-resource this will now parse as
a1=params,
a2=data,
a3=success, // is A Function
a4=error // is A Function
This will be all gibberish unless you use the debugger and look at it running but when you do it will be perfectly obscure
'use strict';
angular.module('MyApp')
.factory('Doc',
[
'$resource',
function DocFactory($resource){
/*You must set de params of the resource*/
return $resource('/db/doc/:dbName/:docId/:docRev',
{
dbName : '#dbName',
docId : '#docId',
docRev : '#docRev'
},
{
upDate: {
method:'PUT',
url : '/db/doc/:dbName/:docId/:docRev' // can change
params: {
dbName : '#dbName',
docId : '#docId',
docRev : '#docRev'
}
}
}
);
}
]
);
....
/*First you must have a Doc resource*/
$scope.upDate = Doc.get({ // or $scope.upDate = new Doc();
dbName : 'someDbName',
docId : 'someDocId',
docRev : 'someDocRev'
}).$promise.then(
function(){
//$scope.upDate is now a Doc,
//Now you can call it here or in other event
$scope.upDate.$upDate({
dbName : 'newDbName',
docId : 'someDocId',
docRev : 'newDocRev'
}).then(
function(){
console.log("OK!")
}
).error(
function(){
console.log("UPS!")
}
);
}
);
I was going through the forEach loop in AngularJS. There are few points that I did not understood about it.
What is the use of the iterator function? Is there any way to go without it?
What is the significance of the key and value as shown below?
angular.forEach($scope.data, function(value, key){});
PS: I tried to run this function without the arguments and it did not work.
Here's my json:
[
{
"Name": "Thomas",
"Password": "thomasTheKing"
},
{
"Name": "Linda",
"Password": "lindatheQueen"
}
]
My JavaScript file:
var app = angular.module('testModule', []);
app.controller('testController', function($scope, $http){
$http.get('Data/info.json').then(
function(data){
$scope.data = data;
}
);
angular.forEach($scope.data, function(value, key){
if(value.Password == "thomasTheKing")
console.log("username is thomas");
});
});
Another question: Why the function above does not enter on if condition and print "username is thomas" in the console?
Questions 1 & 2
So basically, first parameter is the object to iterate on. It can be an array or an object. If it is an object like this :
var values = {name: 'misko', gender: 'male'};
Angular will take each value one by one the first one is name, the second is gender.
If your object to iterate on is an array (also possible), like this :
[{ "Name" : "Thomas", "Password" : "thomasTheKing" },
{ "Name" : "Linda", "Password" : "lindatheQueen" }]
Angular.forEach will take one by one starting by the first object, then the second object.
For each of this object, it will so take them one by one and execute a specific code for each value. This code is called the iterator function. forEach is smart and behave differently if you are using an array of a collection. Here is some exemple :
var obj = {name: 'misko', gender: 'male'};
var log = [];
angular.forEach(obj, function(value, key) {
console.log(key + ': ' + value);
});
// it will log two iteration like this
// name: misko
// gender: male
So key is the string value of your key and value is ... the value. You can use the key to access your value like this : obj['name'] = 'John'
If this time you display an array, like this :
var values = [{ "Name" : "Thomas", "Password" : "thomasTheKing" },
{ "Name" : "Linda", "Password" : "lindatheQueen" }];
angular.forEach(values, function(value, key){
console.log(key + ': ' + value);
});
// it will log two iteration like this
// 0: [object Object]
// 1: [object Object]
So then value is your object (collection), and key is the index of your array since :
[{ "Name" : "Thomas", "Password" : "thomasTheKing" },
{ "Name" : "Linda", "Password" : "lindatheQueen" }]
// is equal to
{0: { "Name" : "Thomas", "Password" : "thomasTheKing" },
1: { "Name" : "Linda", "Password" : "lindatheQueen" }}
I hope it answer your question. Here is a JSFiddle to run some code and test if you want : http://jsfiddle.net/ygahqdge/
Debugging your code
The problem seems to come from the fact $http.get() is an asynchronous request.
You send a query on your son, THEN when you browser end downloading it it execute success. BUT just after sending your request your perform a loop using angular.forEach without waiting the answer of your JSON.
You need to include the loop in the success function
var app = angular.module('testModule', [])
.controller('testController', ['$scope', '$http', function($scope, $http){
$http.get('Data/info.json').then(function(data){
$scope.data = data;
angular.forEach($scope.data, function(value, key){
if(value.Password == "thomasTheKing")
console.log("username is thomas");
});
});
});
This should work.
Going more deeply
The $http API is based on the deferred/promise APIs exposed by the $q
service. While for simple usage patterns this doesn't matter much, for
advanced usage it is important to familiarize yourself with these APIs
and the guarantees they provide.
You can give a look at deferred/promise APIs, it is an important concept of Angular to make smooth asynchronous actions.
you have to use nested angular.forEach loops for JSON as shown below:
var values = [
{
"name":"Thomas",
"password":"thomas"
},
{
"name":"linda",
"password":"linda"
}];
angular.forEach(values,function(value,key){
angular.forEach(value,function(v1,k1){//this is nested angular.forEach loop
console.log(k1+":"+v1);
});
});
The angular.forEach() will iterate through your json object.
First iteration,
key = 0, value = { "name" : "Thomas", "password" : "thomasTheKing"}
Second iteration,
key = 1, value = { "name" : "Linda", "password" : "lindatheQueen" }
To get the value of your name, you can use value.name or value["name"]. Same with your password, you use value.password or value["password"].
The code below will give you what you want:
angular.forEach(json, function (value, key)
{
//console.log(key);
//console.log(value);
if (value.password == "thomasTheKing") {
console.log("username is thomas");
}
});
In Angular 7 the for loop is like below
var values = [
{
"name":"Thomas",
"password":"thomas"
},
{
"name":"linda",
"password":"linda"
}];
for (let item of values)
{
}
Change the line into this
angular.forEach(values, function(value, key){
console.log(key + ': ' + value);
});
angular.forEach(values, function(value, key){
console.log(key + ': ' + value.Name);
});
I am trying to retrieve a data of objects and the result shows on the console but it only shows one result(the last result) on the page.
$http.get('/users').success(function(data) {
$scope.username = data; //assign data to username
console.log(data);
});
And in my Jade template, i have
section(data-ng-controller='browse')
h4 hi
ul(data-ng-repeat='user in username')
li {{user}}
I want to loop through this data
{
"google: xxxxxxxxxxxxx" : {
"name" : "ZZZ YYY",
"profile" : {
"briefProfile" : "Cost call",
"career" : "Web Developer",
"projects" : {
"-JjtSgiwkqFxTxMv0Gip" : "http://zipper.com"
}
},
"provider" : "google"
},
"google:xxxxxxxxxxx" : {
"name" : "SSS TTT",
"profile" : {
"briefProfile" : "Desired Intelligence",
"career" : "Consultant"
},
"provider" : "google"
}
}
Thanks.(i'm not using angularFire).
If you're using the $http service, then you're not using Firebase.
You are repeating the ul instead of the li. Also, {{user}} will be the whole user object, and you will see something like [Object object] on your page instead of a string. So call {{user.name}}.
ul
li(data-ng-repeat='user in users') {{user.name}}
Assuming that $http is there by mistake, and you meant to use Firebase instead, you probably want to start by reviewing the Firebase Getting Started guide
// Get a reference to users
var ref = new Firebase('https://<YOUR-FIREBASE>.firebaseio.com/users');
// Attach an asynchronous callback to read the data at users ref
ref.on("value", function(snapshot) {
console.log(snapshot.val());
$scope.users = snapshot.val();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
If you're using AngularFire you should take a look at this:
Instead of using $http.get try:
var data = $firebaseArray(new Firebase("URL"));
$scope.data = data;
Don't forget to add $firebaseArray as a dependency in your controller.
More info on AngularFire docs:
https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray
If you're not using AngularFire take a look at this:
var firebaseRef = new Firebase('YOUR-FIREBASE-URL/users/');
firebaseRef.on('value', function(dataSnapshot) {
var data = dataSnapshot.val();
console.log(data);
$scope.users = data;
// Might need to use $digest to update $scope.
$scope.$digest();
});
More about on() in Firebase docs:
https://www.firebase.com/docs/web/api/query/on.html
I have an app using routing and I'm working with my first route. The view loads correctly, and I'm able to access data objects in the controller linked to the view, but not the objects created in a function in the controller. Here are code snippets:
html:
<div>
<label>Select Table : </label>
<select ng-init="permits.lookups.selectedLookup = lookupLists[0].list" ng-model="permits.lookups.selectedLookup" ng-options="lookupList.list as lookupList.desc for lookupList in lookupLists" ng-change="populateLookup(permits.lookups.selectedLookup)"></select>
Selected lookup: {{permits.lookups.selectedLookup}}
<table>
<tbody>
<tr><td>first row</td></tr>
<tr ng-repeat="column in columns"><td>{{column.name}}</td></tr>
<tr><td>last row</td></tr>
</tbody>
</table>
</div>
js:
(function() {
var app = angular.module('lookups',[]);
app.controller('UpdateLookups', function($scope, $http) {
var lookups = this;
$scope.lookupLists = [
{list : "0", "desc" : "--Select List--"},
{list : "del_type", "desc" : "Delivery Type"},
{list : "pay_type", "desc" : "Payment Types"},
{list : "trans_type", "desc" : "Transaction Type"}
];
$scope.selectedLookup = $scope.lookupLists[0].list;
$scope.populateLookup = function(lookup) {
$http({
url : <some URL>
dataType : "json",
method : "POST",
data : "action=3&lookup="+lookup,
headers : {"Content-Type" : "application/x-www-form-urlencoded; charset=utf-8"}
}).success(function(data) {
if ( angular.isArray(data.columns)) {
lookups.columns = data.columns;
} else {
lookups.columns = [data.columns];
}
}).error(function(error){
alert("There was an error");
});
};
});
})();
Upon loading, the select options are correctly initialized with the data in the lookupLists object, and when the user changes the selected option, the ng-change directive successfully triggers the populateLookup function, which successfully populates the lookups.columns object. The problem is that I'm having difficulty binding the lookups.columns object with my ng-repeat directive in my table. I've tried to reference the object using columns, lookups.columns, and permits.lookups.columns, yet I cannot seem to access it.
I tried to do something similar in my main controller, and after researching, I found that if I created a variable and assigned "this" to it, then referenced that variable when creating my object, it worked - my assumption is that the assignment of "this" effectively allows the function to assign objects in a scope outside of its own scope. I tried to do that here by creating lookups, but that doesn't seem to be helping here. I can see that lookups.columns is indeed created, but it is not in the $scope of the controller. I'm just learning AngularJS (please be gentle) and still trying to wrap my head around all the binding and scope limitations. I'm guessing that my answer is to build a service/factory and inject it, but when I try to do that based on all of the examples I've seen, it breaks the parts that I have working, so I come back to this starting point, where at least everything else works.
Perhaps you forget '$scope' in front of 'column' variable.
like this:
$scope.populateLookup = function(lookup) {
$http({
url : <some URL>
dataType : "json",
method : "POST",
data : "action=3&lookup="+lookup,
headers : {"Content-Type" : "application/x-www-form-urlencoded; charset=utf-8"}
}).success(function(data) {
if ( angular.isArray(data.columns)) {
$scope.columns = data.columns;
} else {
$scope.columns = [data.columns];
}
}).error(function(error){
alert("There was an error");
});
};