Good afternoon! Learning Angularjs. Below is the structure of the project.
I have a service that reads data from json
var WebKrServices = angular.module('WebKrServices', ['ngResource']);
WebKrServices.factory('DataPlant', ['$resource',
function($resource){
return $resource('plants/:plantId.json', {}, {
query: {method:'GET', params:{plantId:'plants'}, isArray:true}
});
}]);
And Controller
var WebKrControllers = angular.module('WebKrControllers', []);
WebKrControllers.controller('PlantsCtrl', ['$scope', 'DataPlant',
function($scope, DataPlant) {
$scope.plants = DataPlant.query();
}]);
which transmits this information to the html
<div ng-repeat="plant in plants">
<h2 class="text-center">{{plant.name}}</h2>
</div>
And, in fact question. In html I see data from json, and the controller when accessing the plants I see an empty object?
for (var p in plants) {
. . .
}
How to get data from the plants in the controller?
Thank you all for your answers.
Cause it is asynchronous call. After $scope.plants = DataPlant.query();, plants remain undefined until data arrives (Well, it is not exactly undefined, you can inspect it in debugger). When data arrives - $scope.plants get resolved and html is updated. To run some code after data arrives, use callbacks:
$scope.plants = DataPlant.query(function(response) {
console.log($scope.plants);
}, function (response) {
console.log('Error');
});
Related
There is a Webservice that is returning a json object in below format:
["Brazil","Argentina","Chile"]
(this json object has been parsed by Online JSON parsers, which proves it is a proper json object)
In AngularJS, I wrote the below code to consume the WebService.
app.factory('webServiceFactory', ['$http', function ($http) {
return $http.get('http://SomeWebService/api/anOperation')
.success(function (data) {
return data;
})
.error(function (err) {
return err;
});
}]);
When I call this in my controller, the success part is never hit and, instead, the error part is executed. That means there is some error calling the web-service. I think it has to do something with the JSON object that is being returned.
Edit 1: The Controller code
app.controller('mainController', ['$scope', 'webServiceFactory', function ($scope, webServiceFactory) {
webServiceFactory.success(function (data) {
$scope.Countries = data;
});
}]);
Edit 2: Localhost & CORS
When I hosted the service in my local IIS and consumed it using localhost, it worked. That means there is no error in consuming the JSON String array.
However, when I use a Fully qualified name or machine name, the FireFox indicates CORS header missing 'Access-Control-Allow-Origin'.
This might lead to another question, as to how to make it CORS compatible. However, the main question is closed.
So, my question, is How do I consume a web-service in AngularJS that returns just an array of strings with no Key/Value pair?
Thanks
maybe you are doing a request to a service in other domain; that is not possible since exists the "same origin policy" https://www.w3.org/Security/wiki/Same_Origin_Policy
app.factory('webServiceFactory', ['$http', function ($http) {
return
{
getCountries: function(callback){
$http.get('http://SomeWebService/api/anOperation').then(function(reponse){
callback(response.data);
});
}
};
}]);
Then in your controller
webServiceFactory.getCountries(function(countries){
$scope.countries = countries;
});
I have been testing this code for 2 months, it is the first exercise in my tutorial to learn AngularJS.
The challenge is to count all .json files in a folder and increment it with 1 so that when I save another json file it will always have a higher ID then the previous one. I am having lots of trouble with web servers, first of all NodeJS does not seem to allow JSON posts in its standard configuration. So I have found a modified web-server.js from stockoverflow from a different question:
$resource.save is not functioning
https://github.com/glepretre/angular-seed/commit/9108d8e4bf6f70a5145b836ebeae0db3f29593d7#diff-d169b27b604606d4223bd5d85cad7da1 I have also tried the web-server.js that came with the tutorial:
http://pastebin.com/Ckfh4jvD that seemed to work better. WAMP also did not work I could not get Apache to allow JSON posts.
Problem is the web-server posts the json or sees the json as an object not as an array, even though I have used "isArray: true" and I use .query() instead of .get(). And I have tried many other things like transformResponse: []. I need the array to get .length to work! Also sometimes it GETS an array and POSTS an object which it later reads as object again it is getting really weird.
The code works sometimes as posted or sometimes I need to change :id to :id.json, usually this means the server is retrieving it as an object again which is not what I wan but this differs between the 2 nodeJS servers.
.factory('eventData', ['$resource', '$q', function ($resource, $q) {
var resource = $resource('/app/data/event/:id', {id: '#id'}, {"getAll": {method: "GET", isArray: true}});
var number = resource.query();
console.log(number);
return {
getEvent: function () {
var deferred = $q.defer();
resource.get({id: 1},
function (event) {
deferred.resolve(event);
},
function (response) {
deferred.reject(response);
});
return deferred.promise;
},
save: function (event) {
var deferred = $q.defer();
event.id = number.length;
resource.save(event,
function (response) {
deferred.resolve(response);
},
function (response) {
deferred.reject(response);
}
);
return deferred.promise;
}
};
}]);
EDIT: This seems to work better however I need to figure out how to put an .then() into this service?
.factory('eventData', ['$resource', '$q', function ($resource, $q) {
var resource = $resource('/app/data/event/:id.json',
{id: '#id'}, {method: "getTask", q: '*' },
{'query': { method: 'get'}});
var number = resource.query();
I want write two services one with a $http.get method and one with $resource
This service should receive a Json Object and looks like this, at the moment this code is direct in my controller and not in a service:
var csvPromise= $http.get(base_url + 'DataSource/1').success(function(data) {
$scope.data4=JSON.stringify(data);
});
The problem is, I want save received data in $scope.data4 and I want use this data after the $http.get call but the value is empty.
Direct after this call there is and Object that needs this value:
new myObject($scope.data4)
so myObject must wait so long until the data has arrived.
or can I make a synchronous call with $http or $resource ?
How can i do this ? I have found so many examples with promise and .then but nothing has worked for me.
EDIT: I have now written a service but it didn`t work:
var test=angular.module('myApp.getCSV', ['ngResource']);
test.factory('getCSV',function($log, $http,$q, $resource){
return {
getData: function (id) {
var csvPromise= $http.get(base_url +'DataSource/'+id)
.success(function(data) {
return data;
});
return csvPromise;
}
}
});
and then in my controller I call this:
getCSV.getData(1).then(function(theData){
$scope.data4=JSON.stringify(theData);
new myObject( $scope.data4); });
but this did not work. I thought if the $http.get receives the data then the then Function is called.
I don't believe you can do synchronous calls. That said, you have at least two options:
1) Pass in the data using the $routeProvider resolve feature. From the documentation:
An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected
An example on how to use this:
$routeProvider
.when('/your/path', {
templateUrl: '/app/yourtemplate.html',
controller: 'yourController',
resolve: {
data: ['$route', '$http', function($route, $http) {
return $http.get(base_url +'DataSource/1');
}]
}
})
And then in your controller:
app.controller('yourController', ['$scope', 'data', function($scope, data) {
$scope.data4 = JSON.stringufy(data);
var yourObj = new myObject($scope.data4);
}]);
2) The second option is to use promises and only instantiate your new myObject($scope.data4) once the promise successfully completes.
Your code needs to be changed just a bit:
$scope.data4 = '';
var csvPromise= $http.get(base_url +'DataSource/1');
csvPromise.then(function(data){
$scope.data4 = JSON.stringify(data);
}, function(data){
//error handling should go here
window.alert(data);
});
This should give you what it sounds to me like you need.
As i know, there's no way to sync~ call the http or resource. They're hard coded on AngularJS core file :
xhr.open(method, url, true);
And you don't want to hurt your users too by blocking the browser wait the data arrived. You'll better show how you make the nothing has worked for me so we can start working to fix it.
Have you try call new myObject($scope.data4) inside success method?
$http.get(...).success(function(data){
$scope.data4 = JSON.stringify(data); // I've no idea why do you need this.
var stuff = new myObject($scope.data4); // THis is now your.
});
I have a service which retrieves data from the datastore (Web SQL). Afterwards, it stores the data in a AngularJS array. The problem is that this does not initiate changes to the UI.
Contrary, if after the retrieval of data from datastore, I call a web services using a $get method and append the results to the previous array, all data updates the UI.
Any suggestions? Is it possible that I fill the array before the Angular binds the variable?
Can I somehow delay the execution of the service?
Most of the code has been taken from the following example: http://vojtajina.github.io/WebApp-CodeLab/FinalProject/
In order for the UI to magically update, some changes must happen on properties of the $scope. For example, if retrieving some users from a rest resource, I might do something like this:
app.controller("UserCtrl", function($http) {
$http.get("users").success(function(data) {
$scope.users = data; // update $scope.users IN the callback
}
)
Though there is a better way to retrieve data before a template is loaded (via routes/ng-view):
app.config(function($routeProvider, userFactory) {
$routeProvider
.when("/users", {
templateUrl: "pages/user.html",
controller: "UserCtrl",
resolve: {
// users will be available on UserCtrl (inject it)
users: userFactory.getUsers() // returns a promise which must be resolved before $routeChangeSuccess
}
}
});
app.factory("userFactory", function($http, $q) {
var factory = {};
factory.getUsers = function() {
var delay = $q.defer(); // promise
$http.get("/users").success(function(data){
delay.resolve(data); // return an array of users as resolved object (parsed from JSON)
}).error(function() {
delay.reject("Unable to fetch users");
});
return delay.promise; // route will not succeed unless resolved
return factory;
});
app.controller("UserCtrl", function($http, users) { // resolved users injected
// nothing else needed, just use users it in your template - your good to go!
)
I have implemented both methods and the latter is far desirable for two reasons:
It doesn't load the page until the resource is resolved. This allows you to place a loading icon, etc, by attaching handlers on the $routeChangeStart and $routeChangeSuccess.
Furthermore, it plays better with 'enter' animations in that, all your items don't annoyingly play the enter animation every time the page is loaded (since $scope.users is pre populated as opposed to being updated in a callback once the page has loaded).
Assuming you're assigning the data to the array in the controller, set an $scope.$apply() after to have the UI update.
Ex:
$scope.portfolio = {};
$scope.getPortfolio = function() {
$.ajax({
url: 'http://website.com:1337/portfolio',
type:'GET',
success: function(data, textStatus, jqXHR) {
$scope.portfolio = data;
$scope.$apply();
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
};
I'm very new to Angularjs and am having issues figuring out how to update a $scope element I created from JSON. Basically I have a service that contains the function which grabs the JSON:
app.service('JSONService', function($http){
return{
getJSON: function(){
return $http.get('posts.json')
.then(function(response){
return response.data;
});
}
};
});
I then have a Controller that contains a function that gets the JSON data on button click and puts it in $scope.data and a second function that I would like to use to update $scope.data:
app.controller('PostController', function PostController($scope, JSONService){
$scope.data;
$scope.getJSON = function(){
$scope.data = JSONService.getJSON();
};
$scope.addPost = function(){
// Add to $scope.data
};
});
Currently, I successfully grab the JSON data and am able to use it to populate aspects of my view, but I am stuck on how to proceed with updating $scope.data so that:
It actually updates
The update is reflected in my view
I have tried $broadcast, $scope.data.push, $scope.data.posts.push. These have either flat out not worked or given errors. I'm sure it might be a simple answer, but I feel I may be inexperienced with Angularjs and JSON to pick up on it. Thanks in advance.
So I think there are a couple issues with the code above. Hopefully this can help you get it straightened out:
The $http.get() function returns a "promise". Promises have a then() function, which you are using, but you should probably adjust to take the data that gets returned and put it straight into $scope. Doing a "return" statement inside the then() in your service does not really have anywhere to go at that point since the request was async. Angular knows how to work with promises, so you can bind to the data in the UI, but you will actually not find the data directly under $scope.data. $scope.data will still be a promise object, and the data will be in another property (something like $scope.data.promiseData -- don't remember exactly what the property is though). You could adjust like this:
app.service('JSONService', function($http){
return {
getJSON: function() {
return $http.get('posts.json');
}
};
})
Controller:
app.controller('PostController', function PostController($scope, JSONService){
$scope.data;
$scope.getJSON = function(){
JSONService.getJSON()
.then(function (response) {
$scope.data = response.data;
});
};
$scope.addPost = function(postText){
// Add to $scope.data (assuming it's an array of objects)
$scope.data.push({postText: postText});
};
});
HTML:
<div data-ng-repeat="post in data">{{post.postText}}</div>
<input type="text" ng-model="newPostText">
<button type="button" ng-click="addPost(newPostText)">Add Post</button>
Actually, whilst the above code is correct, in this case, the getJSON function isn't actually called anywhere, so the $scope.data is never populated.