here is the problem: I have an Ajax.ActionLink() in which I need to provide a value from textbox for routeValues:
#Ajax.ActionLink("Purchase Tracking", "StatusOfFactor", "Shopping", new { guid = HERE I WANT A JAVASCRIPT FUNCTION TO RETRIEVE VALUE FROM TEXTBOX } , ajaxOptions: new AjaxOptions { UpdateTargetId = "StatusOfFactor", HttpMethod = "GET", InsertionMode = InsertionMode.Replace }, htmlAttributes: new { #class = "btnpeyment btn btn-xs bg-color-btn" })
how should I implement it?
You can replace the Ajax.ActionLink and write some javascript code yourself to achieve what you are after.
To start, we will replace the Ajax action link with a normal anchor tag
<a id="purchasTrackingLink" class="btnpeyment"
href="#Url.Action("StatusOfFactor","Shopping")">Purchase Tracking</a>
<input id="YourTextBoxId" />
Now wireup the click event on this link, prevent the default behavior, read the value of your textbox and use that to generate the new target url and use that for the ajax call.p
$(function(){
$("#purchasTrackingLink").click(function(e){
e.preventDefault();
var textBoxVal=$("#YourTextBoxId").val();
var url=$(this).attr("href");
url=url+"?guid="+textBoxVal;
//Now make the ajax call
$.get(url,function(response){
$("#StatusOfFactor").html(response);
});
});
});
$('#textBoxID').on('change', function(event){
var value = $('#textBoxID').val();
$('#ajaxLinkID').attr('guid', value);
})
Replace the IDs with the ones you are using.
Note: If the textbox was placed on the page via an AJAX call, you will need to use event delegation to make this work, delegate it to the parent container that was originally loaded on the page.
Related
I'm using Metronic bootstrap admin them, which comes with sweetalert - which is an alert library
What I'm trying to do is to do a confirm alert on attempting to delete a record from the table , each row has a delete button
now Metronic has gone and did a little bit of extension on it, so you can now use html 5 "data" attributed to declaratively to declare title, button types etc.
in my MVC app, the following Razor code iterates and adds the button, note that I'm adding the data-id attribute to it - the idea being that I can extract it when the button is clicked to get the id to delete it
e.g.
<button data-id="#u.Id" type="button" class="btn btn-xs btn-circle red btn-delete mt-sweetalert" data-title="Are you sure?" data-type="warning" data-allow-outside-click="true" data-show-confirm-button="true" data-show-cancel-button="true" data-cancel-button-class="btn-danger" data-cancel-button-text="Cancel" data-confirm-button-text="Proceed" data-confirm-button-class="btn-info">
<i class="fa fa-times"></i>
</button>
the following is the Metronic JS extension file - I have added a few lines of code to it, so it calls a custom function on clicking the confirm option.
the idea being that I can leave the additions by Metronic Theme intact and call a custom function on the page where I need it
note that I'm also passing in the $(this) context to my custom function
var SweetAlert = function () {
return {
//main function to initiate the module
init: function () {
$('.mt-sweetalert').each(function(){
var sa_title = $(this).data('title');
var sa_message = $(this).data('message');
var sa_type = $(this).data('type');
var sa_allowOutsideClick = $(this).data('allow-outside-click');
var sa_showConfirmButton = $(this).data('show-confirm-button');
var sa_showCancelButton = $(this).data('show-cancel-button');
var sa_closeOnConfirm = $(this).data('close-on-confirm');
var sa_closeOnCancel = $(this).data('close-on-cancel');
var sa_confirmButtonText = $(this).data('confirm-button-text');
var sa_cancelButtonText = $(this).data('cancel-button-text');
var sa_popupTitleSuccess = $(this).data('popup-title-success');
var sa_popupMessageSuccess = $(this).data('popup-message-success');
var sa_popupTitleCancel = $(this).data('popup-title-cancel');
var sa_popupMessageCancel = $(this).data('popup-message-cancel');
var sa_confirmButtonClass = $(this).data('confirm-button-class');
var sa_cancelButtonClass = $(this).data('cancel-button-class');
$(this).click(function(){
//console.log(sa_btnClass);
swal({
title: sa_title,
text: sa_message,
type: sa_type,
allowOutsideClick: sa_allowOutsideClick,
showConfirmButton: sa_showConfirmButton,
showCancelButton: sa_showCancelButton,
confirmButtonClass: sa_confirmButtonClass,
cancelButtonClass: sa_cancelButtonClass,
closeOnConfirm: sa_closeOnConfirm,
closeOnCancel: sa_closeOnCancel,
confirmButtonText: sa_confirmButtonText,
cancelButtonText: sa_cancelButtonText,
},
function(isConfirm){
//action function on click
if (isConfirm){
swal(sa_popupTitleSuccess, sa_popupMessageSuccess, "success");
//custom function call added by me
//------------------------------------------
if(typeof onConfirmClick === "function")
onConfirmClick.call(this);
//------------------------------------------
} else {
swal(sa_popupTitleCancel, sa_popupMessageCancel, "error");
}
});
});
});
}
}
}();
jQuery(document).ready(function() {
SweetAlert.init();
});
The function in my page:
<script type="text/javascript">
function onConfirmClick() {
alert($(this).data('id'));
//make Ajax call here
}
</script>
Now the problem is, I'm getting the ($this) but not able to get the id or any attribute from the button for that matter
if I print $(this) in console
and just "this"
The question here is:
how can I get the data-id attribute in my function ? if I try $(this).data('id') - I get undefined
Is this the correct approach design wise ? I want to be able to call a custom function on confirm but not disrupt Metronic extensions on sweetalert ?
To pass the id from the button's data-id to the onConfirmClick() function...
I would try to make it transit via a variable.
So on click of a .mt-sweetalert, a SweetAlert is triggered.
Nothing stops you to have another click handler to store the id in a variable accessible by the function.
var sweetAlertId;
$(".mt-sweetalert").on("click", function(){
sweetAlertId = $(this).data("id");
});
Then in the function:
function onConfirmClick() {
alert(sweetAlertId);
//make Ajax request using sweetAlertId here!
}
In short, the id is not forced to transit via SweetAlert!
;)
As the title states, I wrote an ajax function that should scroll to the position the user were before getting redirected.
I wrote an alert for test scenario and it does trigger but the scroll keeps getting back to the top, whave have I done wrong here?
JavaScript:
$.ajax({
type: "GET",
url: "AdminListUsers.aspx?column=Disabled&direc=False&a=chstat&z=+",
success: function loadDoc() {
window.scrollTo(window.pageXOffset, window.pageYOffset);
}
});
C#:
var toggleUrl = "AdminListUsers.aspx?column=" + (IsClicked.FirstOrDefault().Key ?? "Name") + "&direc=" + (IsClicked.FirstOrDefault().Value) + "&a=chstat&q=" + id.ToString() + "&d=" + disabled + "&z=" + Server.UrlEncode(txtSearchFor.Text);
var hl = new HyperLink();
hl.Text = status;
hl.Style.Add(HtmlTextWriterStyle.Color, (disabled ? "red" : "green"));
hl.NavigateUrl = toggleUrl;
hl.Attributes.Add("onclick", "loadDoc();return true;");
cell.Controls.Add(hl);
tr.Cells.Add(cell);
The problem is because it's actually navigating to the link specified in the hyperlink. Then it's also trying to do the ajax request as well.
If ajax is to be used there's no need to have a navigateURL specified, and the default behaviour of the hyperlink needs to be suppressed by the script. Otherwise you'll get a full page refresh and a jQuery ajax request simultaneously. Since you've got jQuery installed you can do this most easily like this:
C#:
var hl = new HyperLink();
hl.Text = status;
hl.ID = "myLink";
hl.Style.Add(HtmlTextWriterStyle.Color, (disabled ? "red" : "green"));
hl.NavigateUrl = "#";
cell.Controls.Add(hl);
tr.Cells.Add(cell);
JS (using unobtrusive event handling):
$(document).ready(function() {
$("#<%= myLink.ClientID %>").click(function(event) {
event.preventDefault(); //stop the normal behaviour of the link
$.ajax({
type: "GET",
url: "AdminListUsers.aspx?column=Disabled&direc=False&a=chstat&z=+",
success: function() {
window.scrollTo(window.pageXOffset, window.pageYOffset);
}
});
});
});
This will stop the link from causing the whole page to be redirected, and just allow the content to be loaded via ajax.
N.B. If you are creating multiple instances of the hyperlink in a table, you would need to use classes rather than IDs to allow jQuery to locate it.
However, I would question what "AdminListUsers.aspx?column=Disabled&direc=False&a=chstat&z=+" actually returns. ormally an aspx page returns a whole HTML page including the <html>, <body> tags etc - if you put this inside another element such as a <div>, it makes your page invalid - you cannot nest <html> tags. If you want to use ajax, you should use a WebMethod (or other type of webservice) to return only the HTML that should actually be inserted into the element.
I'm trying to load different views without reloading using JQUERY > AJAX.
It works fine the first time but the second time it triggers the call and loads the page.
Here is the button I'm using:
First time:
<p>Start <i class="icon arrow-right"></i></p>
Second time:
<p><a href="{{ URL::route('onboarding-ajax', ['i' => '3']) }}" id="next-step" next-step-id="3" >Next</a></p>
Here is the script:
<script>
$('#next-step').on('click', function (e) {
e.preventDefault();
var that = $(this),
url = that.attr('href'),
type = 'GET',
step_id = that.attr('next-step-id'),
width = (step_id / 32)*100 + '%';
$.ajax({
url: url,
type: type,
success: function(response) {
$('#content-wrap').html(response.view);
window.history.pushState({path:url},'',url);
return false;
}
});
});
</script>
Any idea what is being done wrong?
If your #next-step element is inside #content-wrap, it will disappear when you replace #content-wrap contents. If the new contents also have a #next-step inside it, it is a different element with the same ID, and will not have a click handler attached to it like the previous one did.
The easiest way to salvage it is to use a "live" handler - not on the #next-step, but on a parent. Try this:
$('#content-wrap').on('click', '#next-step', function (e) {
This tells #content-wrap to pay attention to a click event on a #next-step. Since you don't replace #content-wrap itself, this handler will persist, and will catch events even if #next-step is replaced.
I'm working on a page which contains various Youtube video thumbnails in divs which have links attached to each <img> and has Masonry on the container to control class switching to resize selected videos.
The idea is that the div is clicked on, which triggers masonry to change the CSS and also triggers an .ajax() request to django which returns the template for the selected video. (And will perform the opposite when you select it again to return the thumbnail template and reset to normal with Masonry).
As it stands I have two javascript functions, one triggering masonry on the div, and then another triggering the ajax request on the video link;
<script>
(function($) {
$(document).ready(function() {
var container = $('.masonry'), masonry;
//masonry = new Masonry(container[0]);
container.masonry('stamp', container.find('.stamp'));
container.unbind('click').on('click', '.item', function() {
var $this = $(this),
this_link = $this.find('a'),
$this_link = $(this_link),
this_href = $this_link.attr('href'),
video_id = $this.attr('data-video-id'),
gigante = $this.hasClass('gigante'),
selector = 'div#panel-area.video_grid div.masonry div.item.' + video_id;
$.ajax({
type: "GET",
async: false,
url: this_href,
timeout: 5000,
data: {'g': gigante},
dataType: 'html',
success : function(data) {
$(selector).html(data);
container.find('.item').removeClass('gigante');
$(this).toggleClass('gigante', !gigante);
container.masonry();
console.log('Selector: ' + selector + '\nSuccess');
}
})
.done(function(msg){
console.log('Done: ' + msg);
})
.fail(function(jqXHR, textStatus){
console.log('Failed: ' + textStatus);
});
});
});
})(jQuery); </script>
And the HTML;
<div class="masonry js-masonry" data-masonry-options='{ "stamp": ".stamp", "isOriginLeft": false }'>
<div class="mpus stamp">
</div>
<div class="item video {{ object.id }}" data-video-id="{{ object.id }}">
<a class="GetYoutubeVideo" href="{% url 'show_video' video_id=object.id %}">
<i class="icon-play-circled play"></i>
<span class="title">
{{ object.get_title|slice:":20" }}...<br/>
{{ object.date_created|date:"d/m/Y" }}
</span>
{{ object.get_img_tag }}
</a>
</div>
</div>
I'm a javascript novice essentially so I'm sure this is a very basic issue. When I run this through chrome dev tools with async disabled I see the ajax request return the expected content, but then ultimately end up on the target page instead of loading the content in to $(selector) as expected.
When I enable async it just instantly fails. I've been reading docs for ages but don't feel like I'm getting anywhere. Any help would be appreciated.
To avoid the default click action, modify your click handler as follows:
.on('click', '.item', function(e) {
var ...
e.preventDefault();
$.ajax({
...
)}
...
})
Adding e to the click handler function means that the event details are available within the function - on the e object you run the preventDefault() method which prevents default actions from occuring - for instance, a hyperlink will no longer navigate to its target.
The event occurs in generally the following manner, though this is don't an in-depth summation:
A click event occurs on the a element.
The click event starts a search for an event handler. Should one not be found on the element that caused then the event will 'bubble' up the DOM tree, one level at a time until it either reaches the root DOM element and cannot go further, or a click handler is found.
At any point, should a click handler be found then the code in the click handler is executed. If the click handler sets preventDefault() on the event object, or returns false then no further action is taken.
If the click handler neither returns false nor sets preventDefault() then the original browser default action will be executed in addition to your own event handler.
Your code in full with modifications:
<script>
(function($) {
$(document).ready(function() {
var container = $('.masonry'), masonry;
//masonry = new Masonry(container[0]);
container.masonry('stamp', container.find('.stamp'));
container.unbind('click').on('click', '.item', function(e) {
var $this = $(this),
this_link = $this.find('a'),
$this_link = $(this_link),
this_href = $this_link.attr('href'),
video_id = $this.attr('data-video-id'),
gigante = $this.hasClass('gigante'),
selector = 'div#panel-area.video_grid div.masonry div.item.' + video_id;
e.preventDefault();
$.ajax({
type: "GET",
async: false,
url: this_href,
timeout: 5000,
data: {'g': gigante},
dataType: 'html',
success : function(data) {
$(selector).html(data);
container.find('.item').removeClass('gigante');
$(this).toggleClass('gigante', !gigante);
container.masonry();
console.log('Selector: ' + selector + '\nSuccess');
}
})
.done(function(msg){
console.log('Done: ' + msg);
})
.fail(function(jqXHR, textStatus){
console.log('Failed: ' + textStatus);
});
});
});
})(jQuery);
</script>
Is there a point to setting a functioning href attribute on your <a> element if you don't want it to actually go to that URL directly?
Not trying to be clever, just asking if there is a specific reason for it.
Because the problem is that your <a> element is still performing its 'normal' duties, i.e. changing the page. I can see you retrieve that URL via jQuery at a later stage, but that shouldn't matter.
Change your used attribute to something that is NOT href:
<a class="GetYoutubeVideo" href="#" data-custom-url="{% url 'show_video' video_id=object.id %}">
And when you need to retrieve the value, just use that new attribute name:
this_href = $this_link.attr('data-custom-url')
Note that I'm not 100% sure if you need the href attribute for masonry. From what I can see from your code examples, it doesn't matter, as long as you're able to retrieve the value from an attribute (not specifically href).
By NOT using the href attribute, you're making sure your <a> element doesn't have an actual URL to refer to when it gets clicked.
Is this an acceptable solution/workaround?
You could simply return false in your click event callback:
container.unbind('click').on('click', '.item', function() {
...
#ajax
...
return false;
});
I believe it's a more practical way of stopping the default action and preventing the event from bubbling up.
I am trying to show an asp:ModalPopupExtender using jQuery, without any success. Here is what I have :
ASP.NET
<asp:ModalPopupExtender BehaviorID="confirmPopup" ID="confirmPopup" runat="server" />
JAVASCRIPT
function ShowConfirmPopup() {
var _id = '#<%= confirmPopup.ClientID %>';
var modal = $find(_id);
modal.show();
}
What happens is that modal is always equal to null, so the popup never gets shown. What am I doing wrong?
$find() is not part of jQuery, but of ASP.NET AJAX. Therefore, you should not prefix the behavior id with a hash sign:
function ShowConfirmPopup()
{
var modal = $find("confirmPopup");
modal.show();
}