form's get method vs angular $http.get request - javascript

I want to make a get request to a specific url through my angular frontend to the expressjs backend, now in my frontend if I do :-
<li>
<a ng-click="givequiz()">GiveQuiz</a>
</li>
and my angular code is:-
$scope.givequiz=function(){
console.log("give quiz");
$http.get('/home/givequiz').then(function(res){
//request is going fine and all
});
}
The above thing is working but I am getting the response as an object, the complete file and url isn't changing and all.
But if i do the form get thing :-
<li>
<form action="http://localhost:8000/home/givequiz" method="GET">
<button type="submit">Give Quiz</button>
</form>
</li>
this takes me to a new url called "http://localhost:8000/home/givequiz"
but the $http.get doesn't why is this so? Aren't both methods same? And that's how I am handling both the requests.
router.get('/givequiz', function(req, res, next) {
console.log("in getquiz");
//always gets printed ^ means all reqs come here
res.sendFile('/givequiz.html',{ root: client });
});
Any help will be much appreciated.

It sounds like your code is working fine. Angular is making an AJAX type request behind the scenes. If you want to change route when the response comes back successfully you should do:
$http.get('/home/givequiz').then(function(res){
// request is going fine and all
$state.go(nameOfState)
});
You could alternatively set window.location in the then resolve block but that will prob cause a page refresh whereas state.go should not.

Related

How to send data from my node script to a function in the client script

I am trying to learn Node.JS by building my own inventory management system. I am trying to learn how to pass data from the HTML page and Client JS script to the server and then return the data to the client JS script.
So far I have created a basic HTML page with the form, I created a client JS script, and Index/Server JS script. The server is the node and uses nedb as the database, and webpack.
My current issue is I can't get the data sent to the server from the HTML form to go to the Client.js function. I have tried using response.sendFile and a few other response. commands but the server keeps saying response.x is not a function (x being sendfile/render/etc...). I am not sure what I am doing wrong, I have included the HTML form, server script and client-side function.
HTML
<div>
<form action='/inventory' method='POST'>
<input type="text" name='Name' value="Name"/>
<input type="text" name='Model-Num' value="Model Number"/>
<input type="text" name='Current-Stock' value="Current Stock Amount"/>
<input type="text" name='Target-Stock' value="Target Stock"/>
<input type="text" name='Reorder-Amount' value="Reorder Amount"/>
<input type="submit" value="Submit"/>
</form>
</div>
==============================
SERVER
app.post('/inventory', urlencodedParser ,(req, response, next) => {
console.log('Im not broken');
console.log("I got a req");
console.log(req.body)
response = {
status: "success",
code : 200,
hype : "SO hyped",
}
console.log("res" , response);
next();
});
=======================
CLIENT
function printHTML(e)
{
console.log("e " , e);
}
I just want the data object from the node function to go to the client-side function.
You need response.status(200).json(yourobject). No need for next() in the route handler.
A major problem is, that you don't have a way to receive the response from the server in the client-side Javascript.
Have you heard about AJAX before? If not, then take a look at it. With AJAX, you can make server calls and get responses back from the server. In your current code, you have no way to receive the server response.
Also, you have the parameter response and then later
response = {
status: "success",
code : 200,
hype : "SO hyped",
}
which overwrites the parameter. This way, response doesn't have the functionalities of the parameter (render, sendFile, etc.) anymore, but of the object, which you defined. So, it is definitely necessary to rename either the parameter or the object.
You're overwriting your response object, which was passed as a parameter from the route handler. Try use a different variable name so you don't overwrite it.
app.post('/inventory', urlencodedParser, (req, response, next) => {
console.log('Im not broken');
console.log("I got a req");
console.log(req.body);
const returnToClient = {
status: "success",
code: 200,
hype: "SO hyped"
};
// You could also use response.send() here, but your response is an
// object so it's better to use response.json()
response.json(returnToClient);
});
Also if you're sending a response back to the client, then you wouldn't really need to use the next() function.

re-render pug view with express

Basically what I wantto achieve is a searchable/filterable listview
so far I'm able to fetch some data from a database and have express with pug render me a page showing the results in a listview.
Now I want to add the functionality of filtering the displayed listview.
Therefore on every keyup event within a textbox I make an AJAX post request to the server sending the query string from the textbox. So far everything works just fine, but when i try to "re-render" the page with the filtered resultset nothing happens in the browser.
My routes look like this:
var rechnungen;
router.get('/', function(req, res) {
connection.query('SELECT * FROM rechnungen ', function(err, result) {
rechnugen = result;
res.render('rechnungen', {rechnungen: result});
});
router.post('/:query', function(req, res) {
console.log("received ajax request");
console.log("with query " + req.params.query);
res.render('rechnungen', {rechnungen: {}});
});
initially the query statement fetches the data and res.render works just fine, when I make the AJAX call everything seems to work as well (the console log output matches my input) but regardless what i try to pass to the view (res.render) in the post route nothing happens.
Is it not possible to "re-render" a view or is there any other conceptional misstake I make?
thanks for your help
AJAX POST call is not a traditional HTTP call.
The rendered page sent from the server will come in the response object of success handler of your AJAX call.
So, either
replace whole HTML with the response HTML, or
make a traditional HTTP form POST, in that case the browser by-default renders the response of the server.

Angular get request

I have a working angular form sitting inside an app (rails app). It sends a get request to a rails server.
The problem is that if this app receives a normal get request, it refreshes the page. However, when the request is sent via angular, I can see the request on the server, but the page is never refreshed. (I can use these get requests to get data back as well).
The question is how do I pass a get request in angular form, so that the server processes it normally, and refreshes the page?
html:
<form ng-submit="submitForm()" style="margin-top:30px;">
<h3>get request</h3>
<button type="submit" class="btn btn-primary">Get</button>
</form>
app.js controller:
$scope.submitForm = function(){
posts.factorySubmit();
};
app.js factory get function:
o.factorySubmit = function() {
$http.get('http://localhost:8080/clients');
};
--Side note - if I create a get request, with regular java script in the app, outside of the angular context, I get expected behavior, the page refreshes.
You've wrapped your $http in a factory which is great practice. What you're not doing is capturing the response.
o.factorySubmit = function() {
// Add a return here
return $http.get('http://localhost:8080/clients'); // This call returns a promise
};
Then when you call this function...
$scope.submitForm = function(){
posts.factorySubmit().then(function(response) {
$scope.requests = response.data; // This is where you get your response
},
function(response) {
// This is your error handling
});
};
The cool thing about angular is that it will detect changes and update the page automatically. It has a digest cycle that is called internally in response to changes. Since you're using the built-in $http provider, it'll refresh when you update the $scope variables.
Angular is by design supposed to not refresh the page as it is built for Single Page Applications. If you want to manually refresh the page, use
$scope.submitForm = function(){
posts.factorySubmit().success(function(){
$route.refresh();
});
};
In the success function of your $get request. Remember to inject $route into your controller.

res.send and res.render calls

I am trying to determine if i can call res.send(data) and then res.render('reports') simultaneously.
To explain further in detail, when i route to '/reports', first on my server side i making a REST call to an API which returns back json data. Now i want this json data to be accessed on the client, for which i am making an ajax call from my javascript. Hence the use of res.send(), but i also want to render the page in this call
So it looks like the following on my server side code
router.get('/reports', function(req,res){
//Making the REST Call to get the json data
//then
res.send(json);
res.render('reports');
});
Every time i hit the '/reports' on the browser, I see the json value instead of the page being rendered and my console throws an Error: Can't set headers after they are sent.
You could use content negotiation for that, where your AJAX request sets the Accept header to tell your Express server to return JSON instead of HTML:
router.get('/reports', function(req,res) {
...
if (req.accepts('json')) {
return res.send(theData);
} else {
return res.render('reports', ...);
};
});
Alternatively, you can check if the request was made with an AJAX call using req.xhr (although that's not 100% failsafe).
No you can't do both, but you could render the page and send the data at the same time:
res.render('reports',{data:json});
and then access those data in the newly rendered page.
alternatively you could send a flag when making the call , and then decide whether you want to render or send based on this flag.
Ideally, it needs to be 2 separate route, one spitting json and other rendering a view. Else, you could pass a url param, depending on which you return json or render a view.
router.get('/reports/json', function(req,res){
var data = JSON_OBJECT;
res.send(data);
});
router.get('/reports', function(req,res){
var data = JSON_OBJECT;
res.render('path-to-view-file', data);
});
No, you can't. You can only have a single response to a given request. The browser is either expecting an HTML document or it is expecting JSON, it doesn't make sense to give it both at once.
render just renders a view and then calls send.
You could write your view to output an HTML document with a <script> element containing your JSON in the form of a JavaScript literal.

POSTing using AngularJS $resource

Using a normal html form, I can add a new task by sending POST request to /api/tasks/insert/
POST data includes $name and $description of the task.
However, when I use Angular to push the data to REST API in php, only a POST request is sent and an empty row is created in the database.
This means that the POST variables are not being passed i.e. name and description.
What am I doing wrong?
I have been stuck at this for the last few hours now. I have checked countless tutorials and am pretty sure of the syntax. My backend REST api in PHP works fine.
var res=$resource('http://localhost/api/tasks/insert/',{},
{
createTask:{method:'POST'}
});
postData={name:"Hello",description:"DescBaby"}
res.createTask({},postData);
//res.createTask(postData); tried this also, but doesn't work
Another variation that I tried based on an comment was this:
res.createTask({name:"TestName", description:"descBaby"}).$promise.then(function(value)
{
console.log("Success"); //I get success in console.
},function(errResponse)
{
console.log("Error");
});
Angular Does not give me any errors. Just sends a blank POST request to the url.
EDIT:
I checked in the network pane in Chrome whether the data was sent or not and as it turns out it is being sent.
However, in the response it's showing this :
Undefined index: name in XYZ.php line ABC.
The line pointed above is the following line in my PHP:
$obj->InsertTask($_POST['name'],$_POST['description']);
Thanks to a friend of mine, I finally got the code running. The problem wasn't with my Angualar Code but with php code.
As it turns out I cannot read POST data as $_POST[].
file_get_contents should be used in such cases as data is sent through a JSON payload and not through request parameters!
Here's how I got it running : Angularjs $http.post, passing array to PHP
Did you look at the network tab of debugger? You can check if valid data was sent to server. If it was ok this is not JS or Angular question. On the first look it seems that you have valid code for angular. Just in case check if you have set proper ajax headers.
"X-Requested-With": "XMLHttpRequest"
Does other AJAX calls work for you?
Try this (and create a factory to follow the best practices):
Service
services.factory("Tasks", function($resource) {
return $resource('http://localhost/api/tasks/insert/', {}, {
createTask: {method:'POST', params: {name:"Hello",description:"DescBaby"}}
})
});
Controller
Tasks.$createTask();

Categories