I am asking this question after searching all over the Internet. I do this a lot with a JEE server and jsps. I am trying with with Node and JQuery and having a hard time getting it to work. I have a form that grabs an input, I do an Ajax post to the server and the server responds by rendering a view based on the input. Seems to me that I should not have to worry about a popup attached to a click event on the client. For the life of me I cannot display the page sent by the server in response to the input. Am I missing something here? Any pearl of wisdom on this use case would be greatly appreciated. I tried some related examples and they don't seen to work. Here is the code. Upon return from the server the HTML is not rendered. I just add the javascript that does the AJAX post and processes the response from the server.
script.
$(document).ready(function() {
$("#dialog").dialog({
autoOpen: false,
modal: true,
title: "Details",
buttons: {
Close: function () {
$(this).dialog('close');
}
}
});
$("#OK").click(function() {
var org = $("#name").val();
if (org == '' ){
alert("Please Fill Required Fields");
} else {
alert("about to post "+org);
$.post("/repost",
{name: org})
.done(function(data) {
alert(data);
$("#dialog").html(data);
$("#dialog").dialog("open");
});
$("#form")[0].reset();
}
});
$("#cancel").click(function() {
$("#form").dialog("close"); // To close the form
});
});
Server code:
app.post('/repost', function(req, res) {
console.log("We are called with ", req.body);
res.render('reposub.jade', {org:req.body.name, title: 'Express' });});
sounds like you're looking for help with $.post:
$.post( "ajax/test.html", function( tx_response ) {
//console.dir(tx_reponse) -- does this have ususal stuff like _data_ and _status_? Or is is a raw HTML response?
if (/* some condition like: tx_response.status === 200 */) {
// if the html is a template, and not a redirect to a new url:
$('.result').html(tx_response.data)
// redirect:
window.location.href = tx_response.data
//...
});
If it is neither a redirect nor a template, but rather a whole new http reply with HTML that the client should load, I think you can use document.write but .. this could be engineered better in that case. Arguably the response should be at most a redirect URL, or a template.
In addition to roberto tomás answer, also make sure your server has CORS support enabled. This is particular useful when:
developing something in local, that is not served by a webserver;
whenever your frontend is not located on the same host (thus ip and port combination) of your backend (in your case your nodejs app)
Useful resources:
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
https://github.com/expressjs/cors
So in my case, I had to have a div element that I can run the html method against. So with a div element created in the body of my html page, I was able to do a $("div.listcontainer").html(data); and my page displayed fine.
Related
I am using Node/Express as a web framework, here is how I structured the delete action (it's nested in a higher level route):
.delete((req, res) => {
db.collection('collection-name').findOneAndDelete({ topic_title: req.body.topic_title},
(err, item) => {
if(err) return console.log(err);
console.log('item deleted');
res.redirect('/');
});
Client-Side request:
$('.delete-button').click(function(){
$('.topic-title').text($('.topic-title').text());
if(confirm('Are you sure you want to delete ' + $('.topic-title').text() + '?')){
fetch('topics', {
method: 'delete',
headers: { "Content-Type" : 'application/json' },
body: JSON.stringify({
'topic_title' : $('.topic-title').text()
})
});
}
When I hit the delete button, the page redirect to an index of all the entries in the db.
The problem is that the deleted entry still displays in the redirected page, until the page is refreshed. I'm also having this problem with the update action.
What am I doing wrong here?
This is the same problem I was having myself although I was using a jQuery $.ajax call in a similar way that you are using the fetch APU.
If you think about what's happening, you are sending a request, separate to the rest of your page, off to the server to trigger the delete action within Express. This in turn is deleting the record from the database. Fine, no problems there.
The problem occurs when the delete action finishes. You are redirecting this to the / route but it is the delete request which is being redirected not an actual request for a page.
I couldn't figure out what was happening intially when I encountered this (earlier today actually). My solution was to, once I knew the database had been updated, remove the element from the page thereby eliminating the need for a page refresh / redirect. My code I have now looks like this:
$(function(){
$('.button').on('click', function(e){
var id = this.id;
$.ajax({
url: '/',
method: "DELETE",
data: {item: id}
})
.done(function(data){
$('#' + id).parent().remove();
});
});
});
There is probably a more elegant way to handle the removal of the (in my case) list item but I haven't got round to looking at that yet.
Also, it might be worth reconsidering the fetch API if this is something more than a personal project as browser support seems to be very limited.
Try to use mongoose instead MongoClient.
It works perfect on my project with similar functions
http://mongoosejs.com/
I load a page from example.com on port 80, then from the loaded page, submit a form to the same server on a different port (as defined in the form action attribute).
(html)
<form id="enabledForm" action="http://example.com:39991/updateEnabled" method="POST">
(javascript)
$('#enabledForm').submit()
This works fine and the data is delivered as expected to the form action url, but the browser is redirected to the address of the POST request instead of staying on the requesting page.
If I use
$('#enabledForm').submit(function (event) {
event.preventDefault();
});
or
$('#enabledForm').submit(function (event) {
return false;
});
then the server receives no data but the page is not redirected.
if I add an alert within the event handler then the alert is not shown.
$('#enabledForm').submit(function (event) {
alert('inside submit event handler');
return false;
});
Clearly I'm soing something wrong but after hours of headbanging and trying everything I can think of I'm stuck.
What to do?
You have two basic options here:
Have the server return a 204 No Content response and forget about using JS entirely
Prevent the submission of the form with JS and send the data to the URL with Ajax instead
No content:
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent.
How you set the HTTP response status code depends on your server side language / framework. For example:
In Catalyst it would be something like:
$c->response->status(204);
In PHP it would be:
http_response_code(204);
There are many Ajax tutorials out there, so I'm not going to provide another one. The jQuery documentation has a detailed section on Ajax.
Note that since you are working across origins (different ports), you will need to circumvent the Same Origin Policy. The standard way to do that is with CORS.
Sending a form would automatically change your browser URL (and refresh view).You should use an Ajax request to send informations to your server and eventually retrieve completion (success, error, informations...).
Extract your inputs' values to an object via Jquery and send your request via Jquery.post or Jquery.get
$('#enabledForm').submit(function (event) {
//Prevent natual post
event.preventDefault();
//Retrieve inputs values
var data = {}
$('#enabledForm input,textarea').each(function(index){
data[$(this).attr('name')] = $(this).val();
});
//Send request
$.post('http://example.com:3999/updateEnabled',data,function(response){
//Parse response if you want to inform user about success of operation
});
});
I don't know if val() is usable with all of yout inputs, but it's easy to adapt...
When running an angularjs application, the user access may be withdrawn from the server side. In this case, every request results in a http 302 redirect and a login html (no partial) page. Since angular does expect whatever it was requesting in case the access would still be given, it breaks as it may expect a json string but gets the html login page.
Is there anything I can do do catch this event (listen to redirects, figure out whether html is returned, etc) and do a "hard" refresh of the redirect url?
Since you can't interfere an ajax 302 response and redirect to an error page, you will need to be a little creative.
You can add a header or a different response code to your relevant responses and add an interceptor on the client end.
The interceptor is a module that every ajax request\response goes throught.
You can add code that will look for that header and simple perform a $window.location.href to the login page.
Read here about interceptors.
Check this example out - It handles 401 responses.
If I get you right you are talking about the $http Service from AngularJS.
If thats the point, you could transform the response by yourself and check if its valide JSON like this:
$http({
url: '...',
method: 'GET',
transformResponse: function (reponse) {
var ret = [];//if the return stays empty, the repsonse may be HTML
try {
ret = JSON.parse(reponse);
} catch (error) {
//here you could check for the error
}
return ret;
}
}).success(function(answer){
if(answer.length === 0){//its empty, so its probably HTML
$window.location.reload();//refresh page here
return;
}
//its JSON with content!
});
I am building a MVC application, and we are using some Ajax calls to an MVC Action like this:
$.ajax({
url: myController/MyAction/1, context: document.body,
success: function (data) {
$('.modal-title').html(title);
$('.modal-body').html(data);
$(this).addClass("done");
$('#myModal').modal('show');
},
error: function (err, status, a, b) { toastr.error(a) }
});
When everything is OK, the Action returns html data and fills the modal body with HTML.
When something goes wrong, it returns status code 400 with a custom message and displays it with toastr (.js - a nice colourful alert box)
Here's the MVC Action called:
public ActionResult MyAction(string id)
{
var viewModel = new partialViewModel();
if (!string.IsNullOrEmpty(id))
{
var data = Get_Html(id); // do something, get the html
if(data == null)
{
// something is wrong, return status code 400 with my custom message
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "My error message.");
}
viewModel.Data = data; // fill the viewModel, the partial view is using
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "My error message.");
}
// return the partial view filled with data as Html
return PartialView("_myPartialView", viewModel);
}
I was inspired by these StackOverflow answers: link 1 and link 2
Everything worked fine on DEV PCs, but then we released the application to the customer's server...
The customer's server security is quite high, so he uses gateways, which scan the responses the app returns.
When something goes wrong (server returns status code 400 and my message to the client), and goes wrong often (twice per sec. for every logged in user), there's a possible scenario, that the gateways could recognize legit requests, which return legit status 400 as DoS attacks and block the poor user's IP.
Another possible scenario is, that one of the gateways can catch my 400, throw it away and return its own custom error with some other status code (and without my custom message!)
Currently I decided to solve it, by returning statusCode 200 (OK) with a special statusText and then inside the Ajax success function determine if there's this special text and show messages:
//... ajax call ...
success: function (htmlData, a, b) {
if (b.statusText.indexOf('INT_ERROR:') == 0) {
toastr.error(b.statusText.replace('INT_ERROR:', ''));
}
else {
// fill and show the modal
}
},
//... the rest ...
But that's not a good solution. Does somebody know a better way? I can not persuade the customer to change his security.
You may also tell me, it IS a good solution. I just don't like it.
Thanks
I am new to nodejs and jquery, I just want to get some data from a server and use that data to update a page:
Client side (uses jquery): as you can see, I want the text inside '#info' change to data got from server.
$('#button').click(function(){
$.post("/search", function(data) {
$('#info').text(data);
});
});
Server side (uses express):
app.post('/search', function(req, res){
res.send('hello');
})
The problem is: instead of updating the content of '#info', the content of the whole webpage will be gone and only 'hello' is printed on the webpage.
The client side seems unable to get the data from the server side, but I cannot figure it out why.
As mentioned in my comments, instead of handling button click event, you could handle form submit event and stop the form from submitting.
$('form').submit(function(){
$.post("/search", function(data) {
$('#info').text(data);
});
// This will prevent further processing...
return false;
});