In my site, there's a pervasive search bar that is a typeahead widget. The widget has a 'selected' callback that I am currently trying to implement.
In the callback, it determines whether or not it needs to make an AJAX request on the existing page or whether it needs to go to another page. My problem is that I cannot find anywhere a way to do a redirect with POSTed variables, like in a jQuery AJAX request. Is there any way to attain a page request with posted variables that will totally refresh the page, like clicking on a normal hyperlink?
Here is my code:
function getData(event, datum, dataset) {
event.preventDefault();
// get controller action portion of current url
var Controller = '<?= preg_replace('/\/.*/', '', preg_replace('/\/.*\/web\//', '', Yii::$app->request->url)) ?>';
var Key;
// get key out of key-value pair - will either be 'game', 'developer' or 'publisher'
for (var k in datum) {
Key = k;
}
// if the controller action is the same as key, then the request is ajax
// this works fine
if (Key === Controller) {
var req = $.ajax( {
type: 'POST',
url: 'getchilddata',
data: { data: datum[Key] },
})
.done(function(data) {
$('#display-div').html(data);
})
.fail(function() {
console.log("Failed");
})
} else { // else we need to go to a page on a different controller action according to Key
// this is the best i've got so far but want it to be better
window.location.href = Key + '/datastream?q=' + datum[Key];
}
}
The only way to achieve this is creating a form with hidden inputs, because you can't send post variables via Javascript, fortunately there is a Jquery plugin who will save you some code, but at the end the plugin just create a hidden form and simulate the redirect sending the form via POST, this is how to use it:
if (Key === Controller) {
$.ajax( {...})
} else {
$().redirect(Key + '/datastream, {'q': 'datum[Key]'});
}
Note: You can pass the method (GET or POST) as an optional third parameter, POST is the default
Related
what i have is an interesting set of code, whats happening here is that during this signup form once the user gets to this point, it will serialize the data into an array and then use an ajax call to post the information to the database, I have a setup with a payment API that i have to call through an iframe to use correctly, (this is the second set of code below the first). these JQuery statements are defined apart from each other, but within the same <script> tag inside the code. The thing is i need the uriEncodedLink variable from this function to be defined in the global scope so it can be accessed later to be useable from the iframe i call for the payment page.
the problem is, no matter what I do, no matter how i define it in the global scope it seemingly always gets reset after the ajax call posts information to the database. i tried using a var = uriEncodedLink and then setting the string to be called equal to that variable which is defined in the global scope, ive used window.uriEncodedLink = "uri to be called" and tried calling it from the window object. however, to no avail, ive console.logged the data all the way up to the ajax call and it seemingly works appropriately, as you can see from my placed console log of the variable right before the ajax call, in the console. the variable has the correct information which is what i want. however when i call on that variable later, (where the iframe to the payment system is) it becomes null, its as if the ajax call is erasing all data and not just the form data. which is not what i want.
is there anyway to get this variable to work appropriately?
**Note: ** it should be noted that i am unable to move the iframe to the same location as the ajax call, doing so results in weird behavior with the form itself. And yes, i have to use an iframe as i have to pass a certain amount of the form data through the iframe to the payment system.
$(document).bind('next.wizard', function () {
if (wizard.current == wizard.total) {
if ($('form').valid() && $('.username-addon').hasClass('available')) {
//submit form
$(document).trigger('modalloading');
var formdata = {};
$($('form').serializeArray()).each(function (i, a) {
formdata[a.name] = a.value;
});
let str = formdata.inputAdminContactName;
const name = str.split(" ", 2);
uriEncodedLink = "Link to be encoded"
window.uriEncodedLink = uriEncodedLink
console.log(window.uriEncodedLink)
$.ajax('submit.ashx?cp='+wizard.current+'&key=<%=xssToken %>', {
dataType: 'json', type: 'POST'
, data: formdata
, success: function(d) {
$('form').submit();
}
, error: function (xhr) {
window.location.reload(true);
}
});
} else {
$(window).trigger('modal.alert', ['The form has not been filled out correctly, please correct the fields on this page.']);
}
} else {
wizard.next(1);
var formdata = {};
$($('form').serializeArray()).each(function (i, a) {
formdata[a.name] = a.value;
});
$.ajax('submit.ashx?cp='+wizard.current+'&key=<%=xssToken %>', {
dataType: 'json', type: 'POST'
, data: formdata
, error: function (xhr) {
window.location.reload(true);
}
});
}
});
$(document).bind('finished.wizard', function () {
$('.progress-bar').css({ width: '100%' });
$('.innerform').html('<div class="finished"><div class="row clearfix">'+
'<div class="col-md-12 column"><div class="panel panel-default">'+
'<div class="panel-heading"><h2 class="panel-title"><span class="step-title">Almost Finished!</h2></div>'+
'<div style="width: 100%; height: 1100px;">'+
'<iframe id="cps-embed" src="'+window.uriEncodedLink+'"' +
'style="margin:0; width:100%; border:none;" scrolling="no" width="100%" height="1100px"></iframe>'+
'</div></div></div></div></div></div>'
).css({opacity:'0',visibility:'visible'}).animate({opacity:'1'});
});
I have an Epi server page template with following property:
[Display(
Name = "Selection Box",
GroupName = Global.GroupNames.Contact
)]
public virtual bool SelectionBox { get; set; }
In the view I have something like this:
#if (PageEditing.PageIsInEditMode)
{
#Html.CheckBoxFor(modelItem => Model.CurrentPage.SelectionBox,
new
{
#class = "toggle",
#data_url = Url.Action("UpdatePage", "DefaultPage"),
})
<script>
$(function () {
$('.toggle').change(function () {
var self = $(this);
var url = self.data('url');
var value = self.prop('checked');
$.ajax({
url: url,
data: { selected: value },
type: 'POST',
success: function (response) {
alert(response);
}
});
});
});
</script>
}
Basically what it does, it when I change checkbox value, it sends request to controller and updates the value on the page. What I'm missing is that when this sucesfully happens, I would like the page reload but I can't find a way to do it.
I'm not using OOTB on page editing here, as I'm looking for a way to give editors some adavnced editing for the component, yet I don't want to build a dojo widget. Any ideas how to make this work?
There is a chapter on "On-page editing with client-side rendering" in the developer guides, see https://world.episerver.com/documentation/developer-guides/CMS/editing/on-page-editing-with-client-side-rendering/
The purpose of using Ajax is to design a SPA (single page application) where no page reload is required. If you are looking for a page reload, you can probably do
window.location.reload();
But a page reload might cause you to lose data return by the Ajax call.
I am experiecing some issues with AJAX updating the page. The actual data in the database is updated but this is not always reflecting in real time on the web page.
For example, I have the following event:
$("#add_note").click(function(e) {
//e.preventDefault();
$("#add_note_form").validate({
rules: {
contact_note: {
required: true
}
},
submitHandler: function(form) {
contact.modal_update({
'obj' : $('#add_note_form'),
'uri' : '/contact/add_note/'
});
}
});
});
This function when a new note is created calls a callback to validate the form fields first and then if successful calls a callback inside a seperate class to conduct the update. See the modal_update class below:
// Update modal
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url);
// Hide Modal
obj.closest('.modal').modal('hide');
// Refresh
this.refresh();
}
This then figures out the correct route to ajax and calls a ajax call back inside the same class:
// AJAX post
this.post_data = function(obj,uri)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
}
});
}
I am then running another class callback to "refresh" the data in all the elements on the page:
this.refresh = function()
{
// Refresh the ajax requests
this.get_contact_data();
this.get_notes();
this.get_contact_log();
this.get_contact_tasks();
}
This class re loads the functions which run on page load to get the inial data into the tables/fields on the page. See "get_notes" below:
// Get notes
this.get_notes = function()
{
// Get all notes and populate table
var log_uri = this.site_url + "/contact/get_notes/" + this.contact_id;
this.get_data(log_uri,function(data) {
notes = $("#contact_notes ul");
notes.empty("");
// Populate the contact fields, assuming there is a result to play with
if (data != false) {
//alert(JSON.stringify(data));
$("#notes-tab .count").html("(" + data.length + ")");
$.each( data, function( key, value ) {
notes.append("<li class='list-group-item' modal-id='editNoteModal' data-target='" + value.ID + "'><div class='row'><div class='col-lg-3'><i class='fa fa-sticky-note mr-3'></i>" + value.timestamp + "</div><div class='col-lg-7'>" + value.note + "</div><div class='col-lg-2'><a href='#' class='edit mr-3'><i class='fa fa-edit mr-1'></i>Edit</a><a href='#' class='delete'><i class='fa fa-times mr-1'></i>Remove</a></div></div></li>");
});
console.log('Notes loaded');
} else {
notes.append("<li>There are currently no notes for this contact</li>");
}
});
}
Now the problem:
For some reason this does not update consistently in real time. The data is updated fine on the server side but on the client side the update/refresh does not always update. I might add a note and get a correct update response but the refresh method seems to be receiving the old data and always be one note behind. So the next time I add a note, the one I added before then appears and so forth.
Another problem I am experiencing is the methods seem to stack on each event so if I add one note (or one of the other methods) I will see the console say "notes loaded" but on the second note it says "notes loaded" twice, then on the 3rd note added 3 times and so forth.
I am sure there must be something fatal flaw in the design of my code here but I am not experienced enough with javascript/jquery to notice what direction I am going wrong so I can fix it.
I thought that this was an issue with ajax caching and not refreshing the result so I have adjusted the ajax request as cache none and also to send no cache headers. I am running in wamp.
In your case, your refresh code will always run before your data got updated. Because ajax is asynchronous so the code behind and below ajax will always execute nearly the time your ajax running.
At the time you run your post_data function to call the API, the refresh function got run too. So it's done before your data got updated.
You should run refresh function inside ajax callback. For example:
this.post_data = function(obj,uri, callback)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
callback();
}
});
}
And in modal_update, you pass refresh function to post_data as a callback:
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url, this.refresh);
// Hide Modal
obj.closest('.modal').modal('hide');
}
You should read more about asynchronous ajax. You can use other tricky solution is setTimeout to run this.refresh but I do not recommend that because you not sure when the update is done.
Here is my code that redirects user to another page
$.ajax({
type: "POST",
url: "ajax/ajax-send-otp.php",
data: {
mynumber: mynumber,
userCountry: userCountry
},
success: function(data) {
if (data == 2) {
$("#otpVerifyDiv").slideDown(500);
window.location = 'free-listing-new.php';
} else {
alert(data);
}
}
});
Now On Another Page There is A Div-Id With #otpVerifyDiv which is hidden. so i wants to show that div. so is it possible to show div after window location. ?
I don't need any parameters to be send with url for some reasons.and also do not need ay other js like jquery-cookies.js
i tried
success: function(data) {
if (data == 2) {
//SHOW DIV
$("#otpVerifyDiv").slideDown(500);
//THAN REDIRECT
window.location = 'free-listing-new.php';
} else {
alert(data);
}
}
My HTML
<div class="form-group" id="otpVerifyDiv" align="center" style="display: none;">
//Some Contetnt Here
</div>
So is it possible ?
My Plan
is jquery provide any temporary storage or else so where i store data and send data from one page to another like cookies session.
First Approach:
Setting a localstorage variable on success:
if (data == 2) {
localStorage.setItem("otp_verified", 1);
window.location = 'free-listing-new.php';
}
Then on free-listing-new.php check:
if ( localStorage.getItem("otp_verified") == 1 ) {
$("#otpVerifyDiv").slideDown(500);
localStorage.removeItem("otp_verified");
}
Second Approach:
On success, post a variable to free-listing-new.php by creating a hidden form with JS:
if (data == 2) {
$('body').append($('<form/>', {
id: 'hiddenForm',
method: 'POST',
action: 'free-listing-new.php',
style: "display:none;"
}));
$('#hiddenForm').append($('<input/>', {
type: 'hidden',
name: 'otp_verified',
value: 1
}));
$('#hiddenForm').submit();
}
Then on free-listing-new.php check posted variable with PHP's super global $_POST['otp_verified']
Since you using php, you can use condition on the header of the page to prevent people from visiting the page unless they are redirected from a specific page.
on the page they are redirecting to, then you have to use the code as stated by Abhijit
You may do this by checking that user came from which url by $_SERVER['HTTP_REFERER']. if you get the free-listing-new.php in HTTP_REFERER you can show the your div which you want.
I think you can set local/session storage on succes if the redirect page is in same domain. On coming to the redirected page check that storage data and display the div.
On the success response, you should use localStorage.setItem("key", "value"); instead of cookie/session. This function will store the value temporarily in your browser storage.
Usage : store value of otp_verified on success side and redirect to free-listing-new.php page and check for value using localStorage.getItem("key"); and then remove the item from local storage using localStorage.removeItem("key");.
Set item in local storage.
localStorage.setItem("key", "value");
Get item from local storage
localStorage.getItem("key");
Remove Item from local storage
localStorage.removeItem("key");
I have this laravel code in my controller detach function.
$input = Input::all();
$product= Products::findOrFail($input['product_id']);
$product->tags()->detach($input['tag_id']);
$product= Products::where('customer_id', Auth::user()->customers_id)->get();
return view('products.tagsdelete', [
'products' => $product,
]);
This works fine, it deletes the tag realation from my pivot table. The only thing that bugs me it that I don't want to reload the page everytime I press the delete button on my view.
( Of course I could make a selection of all tags the user want to delete, but I want to to this live with Ajax )
My problem is, I couldn't find anything that helps me with detachment from laravel + Ajax. I'm quite okay with Javascript and Jquery but Ajax is still a new thing for me..
So can anybody help me there? I'm really stuck.
Thanks for taking your time :)
#Wiriya Rungruang
current controller code:
public function detach()
{
$input = Input::all();
$product= Products::findOrFail($input['product_id']);
$product->tags()->detach($input['tag_id']);
$product= Products::where('customer_id', Auth::user()->customers_id)->get();
}
my button:
<button type="submit" class="delete-tag-btn" data-product_id="{{ $product->id }}" data-tag_id="{{ $tag->id }}"><i class="glyphicon glyphicon-trash"></i></button>
at the bottom of the code the JS:
<script>
$(".delete-tag-btn").on('click', function(){
var url = "{{ route('detach') }}"; // Url to deleteTag function
url += "product_id=" + $(this).data('product_id');
url += "&tag_id=" + $(this).data('tag_id');
// Now url should look like this 'http://localhost/deletetag?product_id=2&tag_id=5
// Send get request with url to your server
$.get(url, function(response){
alert("success");
});
});
</script>
First : You should create function detach tag from product in your controller and return status success or failure(or nothing)
In your controller
function detachTag(){
$input = Input::all();
$product= Products::findOrFail($input['product_id']);
$product->tags()->detach($input['tag_id']);
$product= Products::where('customer_id', Auth::user()->customers_id)->get();
return "Some state for checking it a success or not";
}
Second : Create javascript function for checking when you click on delete button send request with parameter to function that we created in the first step and rerender or remove that tag from your HTML page
**Parameter is mean product_id and tag_id that your want to detach it
In your js
$(".delete-tag-btn").on('click', function(){
var url = "localhost/deletetag?"; // Url to deleteTag function
url += "product_id=" + $(this).data('product_id');
url += "&tag_id=" + $(this).data('tag_id');
// Now url should look like this 'http://localhost/deletetag?product_id=2&tag_id=5
// Send get request with url to your server
$.get(url, function(response){
// Do what you want
});
});
So when you click on .delete-tag-btn It will send request for detach it
While you can right a simple ajax call, send data and return html and replace it with the old html
lets begin :)
first step is to write ajax, and send it when form is submit or any button is clicked (as per your code)
this one is sample ajax, just fill in your data in it.
var BASEURL = window.location.origin + "/your_domain_name/";
$.ajax({
url: BASEURL + "your_route",
type: "POST/GET", //any_one
data: {
// Your data comes here (object)
},
beforeSend: function () {
},
success: function (response) {
console.log(response); // your html in return
},
complete: function (response) {
}
});
now a call will be send with your data to controller respective to specified route you mentioned, processing will be normal.
It will return only html. You can do whatever you want with this html.
One important problem you might face if considering these instructions is, right now the view you are returning is probably of whole page (because the page is been refresh every time), but if you are thinking to replace it with new html, your will only have to return that part of the page may be a single row or something like that. So break your view in many sub views. Php #include(//path) (blade) might come handy. Thats how I use to work. :)