I have an ajax request being called on form submit. The idea is to save a user's account information without a page reload, and give them a handy flash message to let them know the save was successful. I have no problem saving the data, but I do have a problem with avoiding a redirect on the POST (to a white page with the response data). Here's what I have:
In my Jade view
$("form").on("submit", function (e) {
e.preventDefault(); // prevent page reload
$ajax({
type: "POST",
url: '/account',
data: $("#accountForm").serialize(),
success: function() {
// can req.flash even be used here? How might it be?
req.flash('info', {msg: 'Your profile has been updated!'});
}
}
}
In my controller
exports.postAccount = function(req, res, next) {
var userData = req.body;
userData.id = req.user.user_id;
var updateUserCallback = function(err) {
// This is where everything falls apart
// Theoretically this should run the success handler in the ajax response
res.json(true);
// Any response I send changes the view to a white page with the data, e.g.
// res.send(anyData);
// Flash also doesn't seem to work, which seems weird...
req.flash('info', {msg: 'Your profile has been updated!'});
}
// Successfully saves the data, no problems here
UserModel.updateUser(userData, updateUserCallback);
};
Normally in the updateUserCallback I would just render the account view, but that defeats the purpose of ajax. I want to save the user's data without a page reload/redirect, while letting them know that the ajax function completed successfully (or didn't) via req.flash (flash module).
Basically any res.send() or res.json() call puts that data into a plain white page (no view). I suppose that I'm fundamentally misunderstanding how ajax works, but I've followed other examples for jQuery ajax calls in Node and have not been able to avoid the 'white page' problem.
Node:
var updateUserCallback = function(err) {
return res.send({
message: "Your profile has been updated"
});
}
Client-side JS:
success: function(response) {
// can req.flash even be used here? How might it be?
// Nope
//req.flash('info', {msg: 'Your profile has been updated!'});
$('#someModal').show().html(response.message); // just a sample implementation
}
Instead of using the form submit, you can use simple button click so that page will not get reloaded.
Related
let's say I have this route for my rendered HTML:
app.get('/profile/:id', function (req, res) { // my route
res.render('profile', { id: Number(req.params.id) }); // render the file and set a variable
});
and in my client side javascript file for the profile page I want to get data from the server. I request the data when loading the page by sending a user id to the server and the server returns a user object:
$(document).ready(function() {
var user = null;
$.ajax({
type: 'GET',
url: '', // This one is missing here
dataType: 'json'
}).done(function(data){
user = JSON.stringify(data);
});
console.log(user.name);
});
And my server would handle this function:
app.get('', function (req, res) { // missing route
var userId = ; // This is missing
var userObj = getUserById(userId);
res.send(userObj);
});
What route do I have to use? Tutorials say I have to pass in the route like /profile/:id but this route already exists?
I tried defining a new route like:
app.get('/reqUser/:id', function (req, res) { // Ajax route
res.send(getUserById(Number(req.params.id)));
});
and for my Ajax call I pass in the url http://localhost:8888/reqUser/12345 but this seems to be wrong because user is still null after using the Ajax call.
So how can I define a route handling the page and the Ajax call?
Edit: First off, you'll want to fix the bug in your client-side JS, where you are attempting to print user.name before user has been fetched from the server. You can fix this by moving your console.log statement into the done() callback like so:
$(document).ready(function() {
var user = null;
$.ajax({
type: 'GET',
url: '', // This one is missing here
dataType: 'json'
}).done(function(data){
user = JSON.stringify(data);
console.log(user.name); // log here
});
});
Regarding your routes question, you have several options. Below are two common solutions to this problem:
Create a separate api route to distinguish your API requests from your page requests. For example, app.get('/api/profile/:id, (req, res) => {...});'
Add a URL parameter to your AJAX calls specifying the format you want the response to be in, with the default being the page's HTML. For example, your AJAX would send a GET request to the URL /profile/2012?format=json, which would return the profile's information in JSON.
Personally, I prefer the first option, as it makes intent more clear.
I am developing an app with the node, express, and mongoose. In my login module, res.render() the function sends the code back to the client side ajax call as string format data. Whereas I wanted it to render a particular view. ajax call is post type call. I can see the entire HTML in string format in success field of ajax.
I did search for similar problem and solutions, but I couldn't find any. Let me know what I am doing wrong.
Client Side :
$.ajax({
type: 'POST',
url: '/login',
data: userDetail,
success: function(data){
console.log(data);
},
error: function(err){
$("p").text("Invalid User Details")
}
});
Server Side :
app.post('/login', urlencodedParser ,function(req,res){
console.log(req.body);
User.find({name : req.body.name , password : req.body.pass},function(err,data){
if (data.length != 0){
Todo.find({},function(err,todo){
if (err) throw err;
var token = jwt.sign(req.body,config.secret,{
expiresIn : '1h'
});
res.render('todo',{
todos : todo,
token : token
});
});
}
else
res.status(401).json({ msg : "Invalid User" });
});
});
Ajax calls do not, by themselves, change what is displayed in the browser. They just fetch data and your Javascript code them decides what to do with that data. This is true no matter what type of Ajax call it is, GET, POST, etc...
If you want to change the current page to show the content you fetched with Ajax, then you have to insert that content into the current page yourself.
Or, in the case of a POST, perhaps you want to submit an HTML form and then the browser will render the content that comes back from that form post for you, but an ajax post will not change what the browser displays at all.
Submitting an HTML form can be done either via Javascript or via native user actions (without any Javascript). But, for the browser to process the result for you, it has to be the browser submitting the form, not an ajax call sending the form. If an Ajax call sends the form (as in the code you show), then the result just comes back to your Javascript and it's up to your Javascript to decide what to do with that result (insert it in the page, etc...).
I do a jQuery ajax POST which successfully delivers the correct data to the server.
After the POST is complete, the browser has redirected to the post url page... which I don't want. Neither of the alerts occur. The POST data has arrived at the server just fine.
i.e. after the ajax is performed within a page at http://myDomain/myPage.html as shown below, the browser address bar shows http://myDomain:39991/updateEnabled and no alerts have happened.
var enabledAjax = $.ajax({
url: 'http://myDomain:39991/updateEnabled',
method: 'POST',
data: $('#enabledForm').serialize(),
dataType: 'jsonp'
});
enabledAjax.done(function (msg) {
alert('done')
})
enabledStatus.fail(function (jqXHR, textStatus) {
alert('textStatus');
})
In express, i have router.post('/updateEnabled', urlEncodedParser, updEnab);
Within updEnab all I do at the moment is a console.log of req.body and res.end()
I've tried a 'success' method within the ajax params but that doesn't work either.
What am I doing wrong that is causing the redirect to the POST url?
hello when you submit form this is submitting normally so you need to use this.
event.preventDefault()
this will stop stop normal submitting of form.
To stop the redirection you can use the return statement like this:
enabledAjax.done(function (msg) {
return false;
})
Alright, I have this piece of code, straight from the documents which works fine if I leave the setTimeout out of the equation of which redirects a user to where I want them on my service there after.
However if I put the setTimeout in, during the process of the post actually occuring, or right before (not sure which) either way a race condition is created where the post never gets made, and the script redirects accordingly. I am wondering is there another method of handling this where I know the post did/didn't actually make it then redirect. Or how do others handle this situation?
FB.api('/me/feed', 'post', obj.data.fb_post, function(response) {
console.log(response);
if (!response || response.error) {
alert('Error occured');
} else {
//setTimeout(function(){window.location = obj.data.whereTo;}, 3000);
}
});
What is the bestHi everyone, a MVC3 newbie here! please take a look at these:
in my View page, i have there:
<div id = "AccounStatusDiv" class="display-field">
#Html.DisplayFor(m => m.AccountStatus)
<input id="btnBool" type="button" class="btnGrid ActStatBtn" value="#(Model.AccountStatus ? "Deactivate" : "Activate")" onclick="ChangeStatus()"/>
</div>
and a script:
<script type="text/javascript">
function ChangeStatus() {
$.post('#Url.Action("SetAccountStatus", "User")',
{ UserName: "#(Model.UserName)",
accountStatus: "#(Model.AccountStatus)" });
// change the display of the AccounStatusDiv elements, or maybe just reload the div element if possible. is it?
}
</script>
while in my Display Template, i have there:
<div id = "AccountStatusDiv" style="display:inline-block;">
<img src="#Html.Custom().ResolveImage((bool)Model ? imgPositive : imgNegative)" alt="#Model" />
<label> #ResourceManager.Localize(resource, display)</label>
</div>
in the controller:
public ActionResult SetAccountStatus(string userName, bool accountStatus)
{
SecurityManager.GetMembershipProvider().SetStatus(userName, !accountStatus);
return AjaxResult.JsonRedirect("/User/ViewUser?username=" + userName);
}
The results are shown only after I reload the page.
I want to display the updated img, label and btnBool elements right after clicking the btnBool without reloading the whole page. What is the best way in such case?
Please post your code suggestions, it would be a great help for me!
Thanks in advance!
You're only using $.post() to send data (request) to the server. AJAX can be two-fold: send a request, and receive the corresponding response. In your code, you're not receiving data back (or, at least, making the necessary arrangements so that you are).
If the SetAccountStatus action of your UserController is set to return some data back (maybe through return Json(), or similar), you can modify the $.post() call to receive it, and have your Javascript react accordingly using a callback function.
var data = {
UserName: "#Model.UserName",
accountStatus: "#Model.AccountStatus"
};
var call = $.post(
'#Url.Action("SetAccountStatus", "User")',
data
);
// set the success callback here
call.success(function (m) {
// the [m] variable contains the data returned by the server
// during the resolution of your call
// this will be called when your AJAX call succeeds,
// and you can use this opportunity to update the HTML DOM with new data
});
this is to event click in button and without refresh page
$("#btnBool").click(function(e){
e.preventDefault();
//to do your code, you can use `$.ajax` to request and get response from server
$.ajax({
url: '#Url.Action("SetAccountStatus", "User")',
type:"GET",
dataType: 'json',
data: { UserName: "#(Model.UserName)",accountStatus: "#(Model.AccountStatus)" },
async:'true',
success:function (data) {
alert(data);
//success to parsing json if you data type of your response is json
}
});
}
you can use web service to send request and get response from server , and to request,get response from server you can use $.ajax() in jquery http://api.jquery.com/jQuery.ajax/