At this moment I am using laravel. In this context I am having a form which is successfully submitted by using ajax to a controller. and that controller make it to the database. But the problem is as the ajax is doing its job the whole page remain unmoved / unchanged after the submission even the database is updated.
Now what I want
I want to give feedback to the user that your post is successfully submitted there. or what I want to do in further, I want to refresh the section in which the post is collected from the database as this post can be retrieved from there. But by using ajax only.
So there is no need to collect the whole page or refresh.
here is my form structure
`
{{ Form::open(array('route' => array('questions.store'), 'class' => 'form-horizontal' )) }}
blah blah blaaa .......
<script type="text/javascript">
$(".form-horizontal").submit(function(e){
$(this).unbind("submit")
$("#ask").attr("disabled", "disabled")
var that = $(this),
url = that.attr('action'),
type = that.attr('method'),
data = {};
that.find('[name]').each(function(index, value){
var that = $(this),
name = that.attr('name'),
value = that.val();
data[name] = value;
});
$.ajax({
url: url,
type: type,
data: data,
success: function(response){
console.log(response);
}
});
return false;
});
</script>
{{ Form::close() }}
`
As it is very much visible that the post is updated through a route & controller I want to have another dive and a success message at this script to be displayed after the success of posting. I am looking for some professional structure using what there is minimal need to have interaction with the server side and give user a better page viewing experience.
Thanks a lot for helping me in this research.
I am not sure if I understand you well, but if you want to notify the user about the result of an ajax-called db update you need to have
a route for the ajax save db call - it should point to a method that does the db update.
the db update method should return some value indicating the success/failure of update (for example OK or FAIL)
the only result of calling the method will be just plain text page with OK or FAIL as body
fetch the result by ajax and inform user accordingly (after form submit button)
check out the below code for ajax call itself (inside the form submit handler) to see what I mean
var db_ajax_handler = "URL_TO_YOUR_SITE_AND_ROUTE";
var $id = 1; //some id of post to update
var $content = "blablabla" //the cotent to update
$.ajax({
cache: false,
timeout: 10000,
type: 'POST',
tryCount : 0,
retryLimit : 3,
url: db_ajax_handler,
data: { content: $content, id: $id }, /* best to give a CSRF security token here as well */
beforeSend:function(){
},
success:function(data, textStatus, xhr){
if(data == "OK")
{
$('div.result').html('The new Question has been created');
}
else
{
$('div.result').html('Sorry, the new Question has not been created');
}
},
error : function(xhr, textStatus, errorThrown ) {
if (textStatus == 'timeout') {
this.tryCount++;
if (this.tryCount <= this.retryLimit) {
//try again
$.ajax(this);
return;
}
return;
}
if (xhr.status == 500) {
alert("Error 500: "+xhr.status+": "+xhr.statusText);
} else {
alert("Error: "+xhr.status+": "+xhr.statusText);
}
},
complete : function(xhr, textStatus) {
}
});
EDIT: as per comment, in step 2 (the method that is called with AJAX) replace
if($s)
{
return Redirect::route('questions.index') ->with('flash', 'The new Question has been created');
}
with
return ($s) ? Response::make("OK") : Response::make("FAIL");
EDIT 2:
To pass validation errors to the ajax-returned-results, you cannot use
return Response::make("FAIL")
->withInput()
->withErrors($s->errors());
as in your GIST. Instead you have to modify the suggested solution to work on JSON response instead of a plain text OK/FAIL. That way you can include the errors in the response and still benefit from the AJAX call (not having to refresh the page to retrieve the $errors from session). Check this post on the Laravel Forum for a working solution - you will get the idea and be able to fix your code.
Related
I'm using Laravel 5.2. On my index page, I've got a button to add a new entry, which brings up the form in a lightbox. This form then submits via the create method.
I also have each entry listed on this page, with the ability to edit them inline, which submits via the update method.
I've setup validation via a Request. This means when someone misses something on the add, it redirects to the index method with errors. The errors only show though, when the lightbox is triggered by the user.
I know I can use $errors to see any errors, but I don't see how I can differentiate between the create and update forms for the sake of forcing the lightbox to appear on reload with create errors. Is there a way to do that?
Update:
Suggestion was made to use AJAX to bypass the reload issue, but now I'm getting a 422 return:
AJAX call:
(function(){
var submitAjaxRequest = function(e){
var form = $(this);
var method = form.find('input[name="_method"]').val() || 'POST';
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function(data){
console.log(data)
}
});
e.preventDefault();
}
$('form[data-remote]').on('submit', submitAjaxRequest);
})();
Request:
public function response(array $errors)
{
$response = parent::response($errors);
if ($this->ajax() || $this->wantsJson()) {
return $response;
}
return $response->with('requestMethod', $this->method());
}
I've also tested the ajax call and it works fine when the validation rules are met. It only fails if the validation comes back with something incorrect in the input.
You could override the response method so that you can flash the type of request.
In you Request class you could add
public function response(array $errors)
{
$response = parent::response($errors);
if ($this->ajax() || $this->wantsJson()) {
return $response;
}
return $response->with('requestMethod', $this->method());
}
(With ajax you wouldn't need to worry about the page reload so we can just return the original response.)
In the above I'm assuming you're using POST for your create methods and PUT or PATH for your update methods. If this is not the case you could use a way that make sense to you to differentiate between the requests.
Then in your view you could do something like:
#if(session('requestMethod') == 'POST')
https://laravel.com/docs/5.2/responses#redirecting-with-flashed-session-data
If you are going to use ajax, as I mentioned in the comment above, you will need to make sure you use the error method within the ajax call:
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function (data) {
console.log('success', data)
},
error: function (data) {
console.log('error', data)
}
});
Hope this helps!
On a previous ajax call I get all articles for a selected Page.
Then I display them and bind this function - on click - to each of them. This is working only one time.
When I want to change a second or third article the article id inside the ajax call keeps holding its first value.
CKEDITOR.replace( 'editor1' );
function editArticle(article){
// id changes for each article as it is supposed to
var id = article.attr('data-id');
var text = article.html();
$('#ckModal').modal();
$('.modal-title').text('Editing Article: '+id+' on Page: '+pageTitle);
CKEDITOR.instances.editor1.setData(text);
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.on('save', function(e){
e.cancel();
var html = CKEDITOR.instances.editor1.getData();
if(html){
$.ajax({
type: 'POST',
url: '/admin/nodes/edit',
cache: false,
data: {'html' : html,
'articleId' : id }
}).done(function(msg){
// next two lines did not work
//CKEDITOR.instances.editor1.fire('save');
//CKEDITOR.instances.editor1.stop('save');
// id stays the same
console.log(id);
// I echo an 'ok' string when update worked from php
if(msg === 'ok'){
article.html(html);
$('#ckModal').modal('hide');
}else{
//alert(msg);
}
}).fail(function(xhr, status, error){
console.log(JSON.stringify(xhr));
console.log("AJAX error: " + status + ' : ' + error);
});
}
});
}
I had to cancel the save event to get and set Data and perform the ajax call.
But how do I restart or reset the 'save' event - if this is what is causing the problem. I am not so shure anymore ....
Got it working by destroying editor instance in ajax done function and creating a new one after it.
function editArticle(article){
var id = article.attr('data-id');
var text = article.html();
//CKEDITOR.replace( 'editor1' );
$('#ckModal').modal();
$('.modal-title').text('Editing Article: '+id+' on Page: '+pageTitle);
CKEDITOR.instances.editor1.setData(text);
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.on('save', function(e){
e.cancel();
var html = CKEDITOR.instances.editor1.getData();
if(html){
var title = $('.modal-title').html()
$('.modal-title').prepend(spinner);
$.ajax({
type: 'POST',
url: '/admin/nodes/edit',
cache: false,
data: {'html' : html,
'articleId' : id }
}).done(function(msg){
//console.log(id);
$('.modal-title').html(title);
if(msg === 'ok'){
article.html(html);
$('#ckModal').modal('hide');
CKEDITOR.instances.editor1.destroy();
CKEDITOR.replace( 'editor1' );
}else{
//alert(msg);
}
}).fail(function(xhr, status, error){
console.log(JSON.stringify(xhr));
console.log("AJAX error: " + status + ' : ' + error);
});
}
});
}
You are assigning multiple event listeners on your editor instance 'editor1', one for each article. What happens is when you click save, the first listener (the first article assigned) called cancels all others with e.cancel().
I see you achieved what you wanted by destroying your editor. Doing this removes event listeners, and solves your problem. You could achieve the same with calling e.removeListener() in the handler, this way removing itself after the first run and avoiding the need to recreate the editor. Also note that destroying editors and recreating them is leaking memory (some versions worse than others #13123, #12307), so one should probably avoid doing that if possible.
Both solutions make the save button unusable after a save; of course it will work after another article is chosen for editing. So my suggestion is to remove all previous listeners from your save command before assigning a new one, like this:
// ... in function editArticle ...
CKEDITOR.instances.editor1.resize('100%', '350', true);
CKEDITOR.instances.editor1.getCommand('save').removeAllListeners();
CKEDITOR.instances.editor1.on('save', function(e){
// ...
I have a problem with updating database using AJAX and CodeIgniter. When someone posts AJAX form I retrieve data about user from database this way:
class MY_Controller extends CI_Controller
{
public $memberData;
public function __construct()
{
parent::__construct();
$this->memberData= $this->membermodel->getmemberData();
}
}
(Every controller extend MY_Controller, not CI_Controller).
Then I operate on user data and insert it to database. The problem is that if I send AJAX post really fast (few at same time), few inserted rows are identical (except auto-increment row ID). It looks like CodeIgniter did not receive new user data from database (or don't update it before), and I operate on old one.
I send AJAX like this:
$("#form_id").submit(function(event)
{
$form = $(this);
$.post($form.attr('action'), $(this).serialize(), function(HTML)
{
//do something
});
return false;
});
then I operate on something like this:
$CI =& get_instance();
$CI->load->model('membermodel', 'member');
$variab['value3'] = $CI->memberData->member_value3 + 1; //this is the line that need to be new on every call, but it doesnt
$variab['result'] = $this->calculatedata($variab['value3']);
$parameters = array(
'member_value3' => $variab['value3']
);
//update that variable to database, so it should have new value new on next call
$CI->member->updateinfo($parameters);
return $variab['value3'];
At the end I get that value3, base on it my whole script and insert last query to database. Unfortunately like I said if I send many POST requests in the same time that value is constant.
I use this, it should work out of clipboard, I found it a while ago on SO don't remember the source. (will search for it) source.
Please do read comments and do debug using console.
var r;
$("#form_id").submit(function(event){
if (r) {
r.abort(); //abort all previous requests
}
var $form = $(this);
var $inputs = $form.find("input, textarea, select, button"); //serialize all elements in form
var serializedData = $form.serialize(); //serialize data (prep data)
$inputs.prop("disabled", true); //disable inputs
r = $.ajax({
url: $form.attr('action'), //whatever.php
type: "post",
data: serializedData
});
// Callback handler that will be called on success
r.done(function (response, textStatus, jqXHR){
console.log("Form works: " + response);
});
// Callback handler that will be called on failure
r.fail(function (jqXHR, textStatus, errorThrown){
console.error(
"Error: "+
textStatus, errorThrown
);
});
r.always(function () {
$inputs.prop("disabled", false); //enable inputs
});
// Prevent default posting of form
event.preventDefault();
});
Regard to comment: But if somebody change this JS code he still will be able to bug my whole script, I have to get it secured.
Please consider following order of developing.
create form using HTML
create php file that accepts this form and VALIDATES it; debug all possible inputs etc.
create AJAX part
style using CSS, show errors etc.
This way you will never (rarely) have problems in matter you just did.
I have the following Jquery code that listens to a user typing in a captcha and sends an ajax request on each keyup to see if the correct code has been typed:
$('#joinCaptchaTextBox').keyup(function() {
$.get('scripts/ajax/script.php', {
'join_captcha': '1',
'captcha': $('#joinCaptchaTextBox').val()},
function(data) {
var obj = JSON.parse(data);
if(obj.ajaxResponse.status) {
$('#joinCaptchaNotAcceptable').hide();
$('#joinCaptchaAcceptable').show();
}else{
$('#joinCaptchaAcceptable').hide();
$('#joinCaptchaNotAcceptable').show();
}
});
});
The PHP script on the other end just checks the session and replies:
if($siteCaptcha == $_SESSION['secretword']) {
$this->captchaCompare = TRUE;
}else{
$this->captchaCompare = FALSE;
}
This works fine 95% of the time but I'm finding sometimes it reports the captcha typed is incorrect even though its correct. I think this could be because when typed fast many requests are sent to the server and the order or requests coming back isn't the order sent and therefore (as only one will be correct) a prior one is recieved last and incorrect is displayed.
Is there a better way to do this? Is there a way to ensure the last request sent is recieved last? Is there something I'm missing here. I can give more info.
thankyou
Add a timeout so as to not send a request on every keyup when the user types fast:
$('#joinCaptchaTextBox').on('keyup', function() {
clearTimeout( $(this).data('timer') );
$(this).data('timer',
setTimeout(function() {
var data = {
join_captcha: '1',
captcha : $('#joinCaptchaTextBox').val()
};
$.ajax({
url : 'scripts/ajax/script.php',
data: data,
dataType: 'json'
}).done(function(result) {
$('#joinCaptchaNotAcceptable').toggle(!result.ajaxResponse.status);
$('#joinCaptchaAcceptable').toggle(result.ajaxResponse.status);
});
},500)
);
});
I'm working on wordpress theme, you can take a look at: greenzoner.pl. What I want to do is showing all posts usability in the middle div, i.e single posts, comments, attached pictures etc. 2 side divs should never reload. I am open to any alternatives to method I try to use (maybe IFRAME?).
To load sigle post I used jquery .load()
$.ajaxSetup({ cache: false });
$(".openpost, .comments-link").click(function() {
var post_url = $(this).attr("href");
$(".container").load(post_url);
return false;
});
$(".closepost").click(function() {
$(".container").load(index.php .postlist);
return false;
});
I've encountered a major problem - I cant use ajax comments ( i tried many plugins, tutorials, etc, nothing works) - so basicly when you post reply, you get redirected to eg. http://greenzoner.pl/?p=32#comment-26. My current js for comments is:
var commentform = $('#commentform'); // find the comment form
commentform.prepend('<div id="comment-status" ></div>'); // add info panel before the form to provide feedback or errors
var statusdiv = $('#comment-status'); // define the infopanel
commentform.submit(function(){
//serialize and store form data in a variable
var formdata = commentform.serialize();
//Add a status message
statusdiv.html('<p>Processing...</p>');
//Extract action URL from commentform
var formurl = commentform.attr('action');
//Post Form with data
$.ajax({
type: 'post',
url: formurl,
data: formdata,
error: function(XMLHttpRequest, textStatus, errorThrown) {
statusdiv.html('<p class="wdpajax-error" >You might have left one of the fields blank, or be posting too quickly</p>');
},
success: function(data, textStatus) {
if (data == "success")
statusdiv.html('<p class="ajax-success" >Thanks for your comment. We appreciate your response.</p>');
else
statusdiv.html('<p class="ajax-error" >Please wait a while before posting your next comment</p>');
commentform.find('textarea[name=comment]').val('');
}
});
});
and php:
add_action('comment_post', 'ajaxify_comments',20, 2);
function ajaxify_comments($comment_ID, $comment_status) {
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){
//If AJAX Request Then
switch($comment_status){
case '0':
//notify moderator of unapproved comment
wp_notify_moderator($comment_ID);
case '1': //Approved comment
echo "success";
$commentdata = &get_comment($comment_ID, ARRAY_A);
$post = &get_post($commentdata['comment_post_ID']);
wp_notify_postauthor($comment_ID, $commentdata['comment_type']);
break;
default:
echo "error";
}
exit;
}
}
Other problem with using this method, is post linking.