I want to get carData.json file from a server using AngularJS.
Here is how I have structured it:
I have a services.js file (inside of js forlder) where I hold all of my services and factories. Here is the factory that I use to get carData.json file from a server:
carApp.factory('getAllCars', function($http){
return {
get: function() {
return $http.get('data/carData.json');
}
};
});
I also have a CarsByReviewCtrl controller that uses the carData.json file for its purposes:
carApp.controller("CarsByReviewCtrl", function($scope, getAllCars) {
getAllCars.get().success(function(data){
$scope.allCars = data;
}).error(function(data, status, headers, config) {
alert("AJAX failed")
});
$scope.carList = [];
console.log($scope.allCars);
...
And finally here is the end of my .html file where I pass these .js files. (I have called the controller in the middle of my html file)
<script type="text/javascript" src="js/controllers/CarsByReviewCtrl.js"></script>
<script type="text/javascript" src="js/services.js"></script>
</body>
</html>
Now, if I run my app and open the console, I would get the output of undefined, instead of javascript object that I got from the server.
What have I done wrong and how can I fix that?
You are trying to print the content of $scope.allCars before the HTTP request is resolved.
Added some comments to your code in order to explain how you should be reading it:
carApp.controller("CarsByReviewCtrl", function($scope, getAllCars) {
// first line of JS to be invoked
getAllCars.get().success(function(data){
// this will be executed later in time, after receiving the HTTP response (case success)
$scope.allCars = data;
}).error(function(data, status, headers, config) {
// this will be executed later in time, after receiving the HTTP response (case error)
alert("AJAX failed")
});
// this will be executed immediately after the previous JS line: getAllCars.get()
$scope.carList = [];
// this will be executed immediately after the previous JS line
console.log($scope.allCars);
the problem is: console.log($scope.allCars) runs before the success handler runs.
you can change your code to:
carApp.controller("CarsByReviewCtrl", function($scope, getAllCars) {
getAllCars.get().success(function(data){
$scope.allCars = data;
console.log($scope.allCars);
}).error(function(data, status, headers, config) {
alert("AJAX failed")
});
$scope.carList = [];
...
Related
I have a strange situation as follows:
The Web-Client application I'm working is based on JQuery and AngularJS,
I have deployed a TOMCAT server (8.5) and a servlet (JAVA-based developed on Eclipse).
The code sending the requests from follows:
var MyApp = angular.module('MyApp');
MyApp.factory('DB_Services', ['$http' , '$q' , function($http , $q) {
var l_Result ;
var DB_Services = function(p_URL_Root , p_Query) {
var l_deferred = $q.defer();
var l_params = JSON.stringify(p_Query) ;
var l_url = "http://localhost:8080/MEKUWQDispatcher/DispatcherClass";
var l_params = 'request=' + encodeURIComponent(JSON.stringify(p_Query)) ;
var req = { url : l_url,
method :"GET",
timeout:10000 ,
headers: {
'Content-Type': 'application/json ; charset=UTF-8'
},
data:l_params
} ;
$http(req ).
success(function(data, status, headers, config) {
l_deferred.resolve(data);
}).
error(function(data, status, headers, config) {
l_deferred.resolve(status);
});
return l_deferred.promise;
return l_deferred.promise;
} ;
return DB_Services;
}]);
Now, the Servlet includes both GET and POST methods. The GET method works in two ways: If the request contains data, it uses the received data to invoke a DB stored procedure. If no data in the request, it invokes a hardcoded select statement (this second behavior is the simple way I found to verify proper connection to the DB, and it would never be activated in real life; moreover, I may eventually delete that part from the servlet's code).
When using a browser (IE, CHROME, all the same result) and enter the address:
http://localhost:8080/MEKUWQDispatcher/DispatcherClass
I get the result of the hardcoded select statement as expected. If, on the other hand, I enter some data to the request, something like:
http://localhost:8080/MEKUWQDispatcher/DispatcherClass?data="request={blabla}"
I get error 400 (bad request).
Now, switching to the javascript, no patter what I do (with or without data) I always get the result of the hardcoded select statement.
I also added the declaration of the servlet within the web.xml file as follows:
<servlet>
<servlet-name>MEKUWQDispatcher</servlet-name>
<servlet-class>MEKUWQDispatcher.DispatcherClass</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MEKUWQDispatcher</servlet-name>
<url-pattern>/MEKUWQDispatcher</url-pattern>
</servlet-mapping>
Since the original post I made several changes to the service code, being the following a copy of the new code that works like a charm (note also that I switched from GET to POST method):
var MyApp = angular.module('MyApp');
MyApp.factory('DB_Services', ['$http' , '$q' , function($http , $q) {
var DB_Services = function(p_URL_Root , p_Query) {
var l_deferred = $q.defer();
var l_params = JSON.stringify(p_Query) ;
var l_url = "http://localhost:8080/MEKUWQDispatcher/DispatcherClass";
var req = { url : l_url,
method :"POST",
timeout:600000 ,
headers: {
'Content-Type': 'application/json ; charset=UTF-8'
},
params:{request:p_Query}
} ;
$http(req ).
success(function(data, status, headers, config) {
l_deferred.resolve({Server_Response:data , Server_Status: status});
}).
error(function(data, status, headers, config) {
l_deferred.resolve(status);
});
return l_deferred.promise;
return l_deferred.promise;
} ;
return DB_Services;
}]);
I'm new to Angular (few hours new). I'm getting pretty much what I want, by adjusting the demo. But i can't get my AJAX request to work.
I tried various solutions, but on gets in an endless loop (figured out that's the way how Angular works). In an other solution nothing really happens..
My current solution (tried to place the peopleController about everywhere):
Controller:
app.controller('MainController', ['$scope','$http', function($scope,$http) {
//$http is working in this
var scrollItems = [];
for (var i=1; i<=100; i++) {
scrollItems.push('Item ' + i);
}
$scope.scrollItems = scrollItems;
function peopleController($scope,$http){
// Simple GET request example :
$http.get('/public/ajax.php').
success(function(data, status, headers, config) {
console.log("worked");
// this callback will be called asynchronously
// when the response is available
scope.people = data;
}).error(function(data, status, headers, config) {
console.log("fail");
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
}]);
HTML:
<div ng-controller="peopleController">
{{people}}
</div>
But it gives me this error:
Error: [ng:areq] http://errors.angularjs.org/1.3.0/ng/areq?p0=peopleController&p1=not%20aNaNunction%2C%20got%20undefined
at Error (native)
at http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:6:416
at Mb (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:19:510)
at nb (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:20:78)
at $get (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:74:494)
at http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:56:415
at r (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:7:408)
at M (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:56:281)
at g (http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:51:201)
at http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js:50:309
Hope someone can help me out here :)
Other solutions i tried for example
match the controller name in your html and js file, if it's 'peopleController' in you html file name it 'peopleController' in the controller rather than 'MainController'.
than change the line
function peopleController($scope,$http){
to
function peopleController(){
you use dependency injection in the controller function, not on the contained functions, the contained function already have access to $something because they are under the controller function's scope
Your view must refer to the controller you declared, which is MainController:
<div ng-controller="MainController">
{{people}}
</div>
Inside your controller, set people to [] and bound to $scope, remove the parameters you passed in peopleController and initiate the request. Caution: in the success handler, rename scope to $scope.
$scope.people = [];
peopleController(); //initiate your ajax request
function peopleController(){ //remove the parameters
// Simple GET request example :
$http.get('/public/ajax.php').
success(function(data, status, headers, config) {
console.log("worked");
// this callback will be called asynchronously
// when the response is available
$scope.people = data; //scope -> $scope
}).
error(function(data, status, headers, config) {
console.log("fail");
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
peopleController() is misleading; its purpose is to get data. I'd recommend to rename it to getPeople().
If you want a separate controller called peopleController you need to define it separately as follows:
app.controller('MainController', ['$scope','$http', function($scope,$http) {
//$http is working in this
var scrollItems = [];
for (var i=1; i<=100; i++) {
scrollItems.push('Item ' + i);
}
$scope.scrollItems = scrollItems;
}]);
app.controller('peopleController', ['$scope','$http', function ($scope,$http){
// Simple GET request example :
$http.get('/public/ajax.php').
success(function(data, status, headers, config) {
console.log("worked");
// this callback will be called asynchronously
// when the response is available
$scope.people = data;
}).
error(function(data, status, headers, config) {
console.log("fail");
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
}]);
You need to remove $scope and $http from peopleController function which are overriding the existence of $http & $scope
Other thing you should mention ng-controller='MainController' instead of ng-controller='peopleController'
Also change the name peopleController to getPeople. I'm assuming that you want function there instead of controller.
In PHP side there are some element of array:
$this->data['messages']['ms'][] = 'Line1';
$this->data['messages']['ms'][] = 'Line2';
and method that to return json format:
echo json_encode($this->data['messages']); die();
Angular side:
$scope.response = {};
....
request.success(function (data) {
$scope.response.message = data.messages; // Edit here
});
<div ng-repeat="error in response">{{error}}</div>
When I try to get array items, I get nothing
I have converted my difficult object to array:
$scope.messages = [];
...
// In loop
$scope.messages.push(item);
Output in console:
Array[2]0: "Qeydiyyat mümkün deyil. Bu e-mail ilə istifadəçi artıq saytda qeydiyyatdan keçib"1: "Bu IP ünvanından artıq qeydiyyatdan keçilib"
In HTML template I try to display elements:
<div ng-repat="error in messages">{{error}}</div>
you must check your request. Are you useing $http?
Have you provided http in controller/service?
// Simple GET request example :
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
you may also check with console.log(data) if theres any data provided.
Maybe there's different construction than you thought (for example wrapped data)
P.S. it should be messages (with s in the end)
Try this in your angular side.
$scope.response = {};
....
request.success(function (data) {
$scope.message = data.data;
console.log($scope.message);
});
<div ng-repeat="error in message">{{error}}</div>
You call your variable in a wrong way. Try console log the $scope.message if there are data's provided.
I am new to angular and what I am willing to do is replace a piece of code I wrote in the past in jquery to angularjs.
The goal is to take a string from a span element, split it in two and pass the two strings as parameters in a GET request.
I am trying to learn best coding pratices and improving myself so any comments of any kind are always welcome.
Working Code in jquery:
//Get Song and Artists
setInterval(function () {
var data = $('#songPlaying').text();
var arr = data.split('-');
var artist = arr[0];
var songTitle = arr[1];
//Request Lyrics
$.get('lyricsRequester.php', { "song_author": artist, "song_name" : songTitle},
function(returnedData){
console.log(returnedData);
$('#refreshLyrics').html(returnedData);
});
},10000);
Code in Angular
var app = angular.module("myApp", []);
app.factory('lyricService', function($http) {
return {
getLyrics: function($scope) {
//$scope.songArr = $scope.currentSong.split('-'); <-- **undefined currentSong**
//$scope.artist = $scope.songArr[0];
//$scope.songTitle = $scope.songArr[1];
return
$http.get('/lyricsRequester.php', {
params: {
song_author: $scope.artist,
song_name: $scope.songTitle
}
}).then(function(result) {
return result.data;
});
}
}
});
app.controller('lyricsController', function($scope, lyricService, $interval) {
$interval(function(){
lyricService.getLyrics().then(function(lyrics) {
$scope.lyrics = lyrics; <-- **TypeError: Cannot read property 'then' of undefined**
console.log($scope.lyrics);
});
}, 10000);
});
index.html (just a part)
<div class="col-md-4" ng-controller="lyricsController">{{lyrics}}</div>
<div class="col-md-4"><h3><span id="currentSong" ng-model="currentSong"></span></h3><div>
You need to be careful with your return statement when used in conjunction with newlines, in these lines:
return
$http.get('/lyricsRequester.php',
If you don't, JS will automatically add a semicolon after your return, and the function will return undefined.
Move the $http.get statement to the same line as your return statement.
return $http.get('/lyricsRequester.php', ...
Refer to the following docs:
MDN return statement
Automatic Semicolon Insertion
As for your second issue, you $scope is not really something you inject into your services (like $http). Scopes are available for use in controllers.
You need to refactor your code a bit to make things work.
eg. Your getLyrics function can take a song as a parameter. Then in your controller, you call lyricsService.getLyrics(someSong). Scope access and manipulation are only done in your controller.
app.factory('lyricService', function($http) {
return {
getLyrics: function(song) {
var songArr = song.split('-');
var artist = songArr[0];
var songTitle = songArr[1];
return $http.get('/lyricsRequester.php', {
params: {
song_author: artist,
song_name: songTitle
}
}).then(function(result) {
return result.data;
});
}
}
});
app.controller('lyricsController', function($scope, lyricService) {
$scope.currentSong = 'Judas Priest - A Touch of Evil';
$interval(function(){
lyricService.getLyrics($scope.currentSong).then(function(lyrics) {
$scope.lyrics = lyrics;
console.log($scope.lyrics);
});
}, 10000);
});
You also have some other issues, like using ng-model on your span. ng-model is an angular directive that is used in conjunction with form elements (input, select etc.), not a span as you have. So you might want to change that into an input field.
$http does not use .then, it uses .success and .error. the line that you have where it says then is undefined, should be replaced with a success and error handler instead. Below is a sample from the docs:
// Simple GET request example :
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
See Link:
https://docs.angularjs.org/api/ng/service/$http
In angular im using $http.post for sending an id to a php script in order to use this id for a mysql request.
This is my controller:
function ProjectDetailsCtrl($scope, $http, $timeout, getGoodIdProjectDetails) {
$scope.idProjectDetails = getGoodIdProjectDetails.getId(); //Getting id project
$scope.$emit('LOAD')
$scope.url = 'scripts/findProjectDetails.php';
$http.post($scope.url, { "idProject" : $scope.idProjectDetails}).
success(function(data, status) {
$scope.projectDetails = {};
$scope.projectDetails.details = data;
$scope.$emit('UNLOAD')
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
}
idProjectDetails is a number.
Then the Php script :
<?php
$idProject = json_decode($_POST['idProject']);
Php script returns that $idProject is undefined.
Can you help me with this ?
Edit : I tried this way but my app crashed with this :
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
$http({
method: 'POST',
url: 'scripts/findProjectDetails.php',
data: "idProject" : $scope.idProjectDetails
}).success(function(data, status) {
$scope.projectDetails = {};
$scope.projectDetails.details = data;
console.log(projectDetails.details);
$scope.$emit('UNLOAD')
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
With the first example, in Chrome console, the "request playload" contain this : {idProject:1} idProject:1 so I assume my variable is correctly passed through the php script?
There is much confusion among newcomers to AngularJS as to why the $http service shorthand functions ($http.post(), etc.) don’t appear to be swappable with the jQuery equivalents (jQuery.post(), etc.) The difference is in how jQuery and AngularJS serialize and transmit the data. Fundamentally, the problem lies with your server language of choice being unable to understand AngularJS’s transmission natively ... By default, jQuery transmits data using Content-Type: x-www-form-urlencoded and the familiar foo=bar&baz=moe serialization. AngularJS, however, transmits data using Content-Type: application/json and { "foo": "bar", "baz": "moe" } JSON serialization, which unfortunately some Web server languages—notably PHP—do not unserialize natively.
So concretely, your $_POST variable is empty !
To go through this problem there're 2 solutions:
Change the data format in Angular config
Change the way to get the datas with PHP(Deprecated but works)
I haven't invented anything here, just linking...
Hope it'll help.