Goal: Call a server side method asynchronously from changing a dropdown to get data and populate a separate listbox not using UpdatePanels.
Currently I'm using a static ASP.NET page method asynchronously using jQuery and an ajax call as shown in this post (How to wire up a DropDownList to make AJAX calls to the server?) and it is working well.
The whole purpose was to prevent using the UpdatePanel tangled mess that I had been in previous years and this seems to be a good alternative. What I didn't realize is that the page method has to be static and you can not access any of the page's controls or context. So trying to make this call from a dropdown selection to populate another control's data is not possible. I can't see the other controls.
So what I'd like to do before I give up and go back to updatepanels is try to do 1 of the following:
Have my static page method return a json string with my collection data that I then use in the original jQuery method wired up to the change method of the dropdown to populate the separate listbox.
Same as above but return a .NET IList<> or comparable if returning json is not a good idea.
Point is I want that static method to return the needed data to bind to my listbox control. However I don't know how to do this. Here is my current jQuery method:
<script type="text/javascript">
$(document).ready(function () {
// Add the page method call as an onclick handler for the control.
$("<%= MyDDL.ClientID %>").click(function () {
$.ajax({
type: "POST",
url: "Default.aspx/MyDDL_SelectedIndexChanged",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
});
});
</script>
Here is the original dropdown:
<asp:DropDownList ID="MyDDL" runat="server" Width="340px" />
Here is the control that needs populated based on the selection of the dropdown after calling the static method named MyDDL_SelectedIndexChanged:
<asp:ListBox ID="ListBox2" runat="server" Width="340px" SelectionMode="Multiple" />
Here is my current static page method:
[WebMethod]
public static string MyDDL_SelectedIndexChanged()
{
var myClass = new MyClass()
var data = myClass.GetDataCollection()
JavaScriptSerializer serializer = new JavaScriptSerializer();
string jsonString = serializer.Serialize(data);
}
Is there a way to take this returned data and bind it in the jQuery method above? My bailout is to go back to using an UpdatePanel where my server-side method can access other controls, but I really do not want to do this.
There is a javascript project called jsRender that may be what you need:
http://weblogs.asp.net/stevewellens/archive/2011/12/01/goodby-jquery-templates-hello-jsrender.aspx
I actually was looking for a more complete exaample and have the solution working with the code below:
$(document).ready(function () {
MyDDL_OnChangeHandler();
});
function MyDDL_OnChangeHandler() {
// Add the page method call as an change handler for the MyDDL DropDownList.
// This will call the static page method, and use the returned results to populate the 'MyListBox' listbox control.
$('#<%=MyDDL.ClientID %>').change(function () {
var val = $(this).val();
var text = $(this).children("option:selected").text();
var $lbxCtrl = $('#<%=MyListBox.ClientID %>');
$lbxCtrl.attr('disabled', 'disabled');
$lbxCtrl.empty();
$lbxCtrl.append('<option value="0">< Loading Please Wait... ></option>');
$.ajax({
type: "POST",
url: "Default.aspx/MyDDL_SelectedIndexChanged",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{'ID':'" + val + "', 'Name':'" + text + "'}",
success: function (data) {
$lbxCtrl.removeAttr('disabled');
$lbxCtrl.empty();
if (data.d == null) {
return;
}
$.each(data.d, function (i, data) {
$users.append('<option value="' + data.Value + '">' + data.FullName + ' (' + adUser.data+ ')' +'</option>');
});
},
error: function () {
$lbxCtrl.empty();
$lbxCtrl.append('<option value="0">< Error Loading Data ></option>');
alert('Failed to retrieve data.');
}
});
});
As Michael B mentioned in the comments, you can handle any data returned from the ajax call by using success:
<script type="text/javascript">
$(document).ready(function () {
// Add the page method call as an onclick handler for the control.
$("#<%= MyDDL.ClientID %>").click(function () {
$.ajax({
type: "POST",
url: "Default.aspx/MyDDL_SelectedIndexChanged",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
// do stuff with the "data" that is returned
},
error: function(data) {
// handle any errors here
}
});
});
});
</script>
Related
I have a Dropdownlist control in one of my ASCX page.
<asp:DropDownList ID="demoddl" runat="server" onchange="apply(this.options[this.selectedIndex].value,event)" onclick="borderColorChange(this.id, 'Click')" onblur="borderColorChange(this.id)" CssClass="dropDownBox" DataTextField="EmpName" DataValueField="EmpID">
My objective is to fill this Dropdownlist with 'EmpID' as value attribute and 'EmpName' as text attribute.
JS code to fetch these 'EmpName' and 'EmpID' values are as follows :
$(document).ready(function ()
{
loadSavedFreeTextSearchCombo();
}
function loadSavedFreeTextSearchCombo() {
var params = {
loginID: $('#loginID').val()
};
var paramsJSON = $.toJSON(params);
$.ajax({
type: "POST",
url: _WebRoot() + "/Ajax/EmpDetails.asmx/GetEmp",
data: paramsJSON,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
$('#demoddl').empty();
$('#demoddl').append($("<option></option>").val(0).html("--Employee Names --"));
$.each(data.d, function (index, value) {
$('#demoddl').append($("<option></option>").val(value.EmpID).html(value.EmpName));
});
},
error: function () {
showError("Failed to load Saved Search Data!");
}
});
}
Although the entire code runs without any error (the EmpDetails.asmx method returns the valid data successfully), the dropdwonlist doesn't get filled with the required data returned.
What am I doing wrong? I guess somehting's wrong at my 'success' event code
Since you're intended to use DropDownList server control ID as selector, it is necessary to set ClientIDMode="Static", especially if you're using <asp:ContentPlaceHolder> or <asp:Content> to prevent ASPX engine creating <select> element with id attribute containing dropdown's placeholder name:
<asp:DropDownList ID="demoddl" runat="server" ClientIDMode="Static"
onchange="apply(this.options[this.selectedIndex].value,event)"
onclick="borderColorChange(this.id, 'Click')"
onblur="borderColorChange(this.id)"
CssClass="dropDownBox" DataTextField="EmpName" DataValueField="EmpID">
If you cannot use ClientIDMode="Static" attribute for certain reasons (e.g. avoiding multiple <select> elements with same ID), use ClientID property of the control as selector, i.e. <%= demoddl.ClientID %>:
$.ajax({
type: "POST",
url: _WebRoot() + "/Ajax/EmpDetails.asmx/GetEmp",
data: paramsJSON,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
$('#<%= demoddl.ClientID %>').empty();
$('#<%= demoddl.ClientID %>').append($("<option></option>").val(0).html("--Employee Names --"));
// recommended to check against undefined here
$.each(data.d, function (index, value) {
$('#<%= demoddl.ClientID %>').append($("<option></option>").val(value.EmpID).html(value.EmpName));
});
},
error: function () {
showError("Failed to load Saved Search Data!");
}
});
That's my script on my view.
$(function () {
$('#buttonx').on("click", function (e) {
e.preventDefault();
$.ajax({
url: 'Ficha/VerificarPatrocinador',
contentType: 'application/json; charset=utf-8',
type: 'GET',
dataType: 'json',
data: {i: 100036},
success: function (data) {
$(data).each(function (index, item) {
//$('#NomePatr').append(item.Nome)
$("#NomePatr").val(item.Nome);
});
}
});
});
});
</script>
That's my action on my controller.
public JsonResult VerificarPatrocinador(int i)
{
var db = new FMDBEntities();
db.Configuration.ProxyCreationEnabled = false;
db.Configuration.LazyLoadingEnabled = false;
var consulta = db.Tabela_Participante.Where(p => p.ID_Participante == i);
return Json(consulta.
Select(x => new
{
Nome = x.Nome
}).ToList(), JsonRequestBehavior.AllowGet);
}
I'm a newbie in Ajax/Jquery, when I exclude the parameter it is ok, however, when I try to put the data: {i: 100036} in my script and the parameter in my action. It doesn't work. Why is it happening?
The controller is going fine. The parameter even passes, but I can't return this result in my View.
Thank you.
use [HttpPost] attribute on your controller method
[HttpPost]
public JsonResult VerificarPatrocinador(int i)
{
//Write Your Code
}
and change the ajax type attribute from "GET" to "POST" and use JSON.stringify. Also check the url carefully. your ajax should look like this
$(function () {
$('#buttonx').on("click", function (e) {
e.preventDefault();
$.ajax({
url: 'Ficha/VerificarPatrocinador',
contentType: 'application/json; charset=utf-8',
type: 'POST',
dataType: 'json',
data: JSON.stringify({i: 100036}),
success: function (data) {
$(data).each(function (index, item) {
//$('#NomePatr').append(item.Nome)
$("#NomePatr").val(item.Nome);
});
}
});
});
});
Hope it will help you
I think that #StephenMuecke may be on to something, because I was able to reproduce the (intended) logic with a new project.
The first thing to determine is where the code is going wrong: the server or the client.
Try using the Visual Studio debugger, and placing a breakpoint in VerificarPatrocinador. Then run the client code to see if the breakpoint is hit. When this succeeds, this means the problem is on the client end.
From there use the web browser's debugger in order to determine what is happening. Use the .fail function on the return result from .ajax in order to determine if there was a failure in the HTTP call. Here is some sample code that you can use to analyze the failure:
.fail(function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
});
For more information check out http://api.jquery.com/jquery.ajax/
Change following code when ajax success
$.each(data, function (index, item) {
$("#NomePatr").val(item.Nome);
});
because when you are getting data as object of array, array or collection you can iterate using this syntax and then you can pass to var,dom...and so on where you want to display or take.
jQuery.each() means $(selector).each() you can use for dom element like below syntax: for example
<ul>
<li>foo</li>
<li>bar</li>
</ul>
<script>
$("li").each(function( index ) {
console.log( index + ": " + $( this ).text() );
});
</script>
Using GET is working fine but if it is not secure because data is visible to user when it submit as query string.
while post have
Key points about data submitted using HttpPost
POST - Submits data to be processed to a specified resource
A Submit button will always initiate an HttpPost request.
Data is submitted in http request body.
Data is not visible in the url.
It is more secured but slower as compared to GET.
It use heap method for passing form variable
It can post unlimited form variables.
It is advisable for sending critical data which should not visible to users
so I hope you understand and change ajax type:'GET' to 'POST' if you want.
$.each() and $(selector).each()
Change this line
url: 'Ficha/VerificarPatrocinador'
to:
url: '/Ficha/VerificarPatrocinador'
Because when you use this url "Ficha/VerificarPatrocinador", it will call the API from url: current url + Ficha/VerificarPatrocinador,so it isn't correct url.
I have an HTML able, which I bind by using the following Action in MVC controller:
public ActionResult BindTable(int ? page)
{
int pageSize = 4;
int pageNumber = 0;
List<Users> _users = query.ToList();
return View(_users.ToPagedList(pageNumber, pageSize));
}
Below the table I have the following HTML:
<textarea class="form-control" style="resize:none;" rows="9" placeholder="Enter value here..." id="txtValue"></textarea>
<br />
<button style="float:right; width:100px;" type="button" onclick="CallFunction()" class="btn btn-primary">Update specific record</button>
The Javascript function responsible for calling the action is as following:
function CallFunction() {
if ($('#txtValue').val() !== '') {
$.ajax({
url: '/User/UpdateUser',
type: 'POST',
data: { txt: $('#txtValue').val() },
success: function (data) {
$('#txtValue').val('');
alert('User updated!');
},
error: function (error) {
alert('Error: ' + error);
}
});
}
And here is the Action responsible for updating the user:
public ActionResult UpdateUser(string txtValue)
{
var obj = db.Odsutnost.Find(Convert.ToInt32(1));
if(obj!=null)
{
obj.Text= txtValue;
obj.Changed = true;
db.SaveChanges();
return RedirectToAction("BindTable");
}
return RedirectToAction("BindTable");
}
Everything works fine. But the table doesn't updates once the changes have been made ( it doesn't binds ?? )...
Can someone help me with this ???
P.S. It binds if I refresh the website.. But I want it to bind without refreshing the website...
I created a BIND function with Javascript, but it still doesn't binds:
function Bind() {
$(document).ready(function () {
var serviceURL = '/User/BindTable';
$.ajax({
type: "GET",
url: serviceURL,
contentType: "application/json; charset=utf-8",
});
});
}
You're not actually updating the page after receiving the AJAX response. This is your success function:
function (data) {
$('#txtValue').val('');
alert('User updated!');
}
So you empty an input and show an alert, but nowhere do you modify the table in any way.
Given that the ActionResult being returned is a redirect, JavaScript is likely to quietly ignore that. If you return data, you can write JavaScript to update the HTML with the new data. Or if you return a partial view (or even a page from which you can select specific content) then you can replace the table with the updated content from the server.
But basically you have to do something to update the content on the page.
In response to your edit:
You create a function:
function Bind() {
//...
}
But you don't call it anywhere. Maybe you mean to call it in the success callback?:
function (data) {
$('#txtValue').val('');
Bind();
alert('User updated!');
}
Additionally, however, that function doesn't actually do anything. For starters, all it does is set a document ready handler:
$(document).ready(function () {
//...
});
But the document is already loaded. That ready event isn't going to fire again. So perhaps you meant to just run the code immediately instead of at that event?:
function Bind() {
var serviceURL = '/User/BindTable';
$.ajax({
type: "GET",
url: serviceURL,
contentType: "application/json; charset=utf-8",
});
}
But even then, you're still back to the original problem... You don't do anything with the response. This AJAX call doesn't even have a success callback, so nothing happens when it finishes. I guess you meant to add one?:
function Bind() {
var serviceURL = '/User/BindTable';
$.ajax({
type: "GET",
url: serviceURL,
contentType: "application/json; charset=utf-8",
success: function (data) {
// do something with the response here
}
});
}
What you do with the response is up to you. For example, if the response is a completely new HTML table then you can replace the existing one with the new one:
$('#someParentElement').html(data);
Though since you're not passing any data or doing anything more than a simple GET request, you might as well simplify the whole thing to just a call to .load(). Something like this:
$('#someParentElement').load('/User/BindTable');
(Basically just use this inside of your first success callback, so you don't need that whole Bind() function at all.)
That encapsulates the entire GET request of the second AJAX call you're making, as well as replaces the target element with the response from that request. (With the added benefit that if the request contains more markup than you want to use in that element, you can add jQuery selectors directly to the call to .load() to filter down to just what you want.)
I am working on javascript widget which can be shown on any site.
see.
Show JS(jQuery) widget on any site, with ASP.NET MVC server side
Embeddable widgets using jQuery and ASP.NET MVC
and for now I faced with issue, when I need to navigate between pages in widgets. See code below. But for now I am confused how to organize navigation (link clicking, ajax updating) in html that comes from server, to make it working as without widget, because I want to debug it as usual page.
<img alt="TEST" onclick="window.zs.LoadStep1('ad507a69-d882-41d4-8300-bd9f7163d419',this);" style="cursor:pointer;"/>
;
(function (window, ZS, undefined) {
var zs = window.zs = ZS || {};
zs.Version = "v1_0";
zs.baseUrl = "http://localhost/w/";
var jQueryScriptOutputted = false;
var containerSelector = '#zaprosWidgetContainer';
function initJQuery() {
if (typeof (jQuery) == 'undefined') {
if (!jQueryScriptOutputted) {
jQueryScriptOutputted = true;
document.write("<scr" + "ipt type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js\"></scr" + "ipt>");
}
setTimeout("initJQuery()", 50);
}
};
function initContainer() {
if ($(containerSelector).length == 0) {
$('<div id="zaprosWidgetContainer" style="width=500px;height:500px;"></div>').appendTo('body');
}
}
zs.LoadStep2 = function (serviceId) {
$.ajax({
url: zs.baseUrl + 'Wizard/Step2JsonP?jsoncallback=?',
data: { serviceId: serviceId },
type: "GET",
dataType: "jsonp",
jsonpCallback: "callBack",
success: function (json) {
$(containerSelector).html(json.Html);
}
});
},
zs.LoadStep1 = function (providerId) {
$(function () {
$.ajax({
url: zs.baseUrl + 'Wizard/Step1JsonP?jsoncallback=?',
data: { providerId: providerId },
type: "GET",
dataType: "jsonp",
jsonpCallback: "callBack",
success: function (json) {
$(containerSelector).html(json.Html);
}
});
});
};
initJQuery();
initContainer();
})(window, window.zs || {});
I understand that you want to navigate to LoadStep1/LoadStep2 without ajax-style?
You could create a master page in ASP.NET that has a link/button to navigate to the next step. That link is generated as part of the previous step.
E.g. on the output html of Step1 add
Next Step
Can you tell us why you have to create a "non-widget mode" for debugging? What's the difference for debugging?
Something else about JsonP that helped me:
You can also extend your JsonP class that wraps the JSON data into a JsonP string to support returning normal JSON when no callback method is supplied - this way you can use the same uri to return the html directly. I use that to allow widgets run in JsonP and Json simultaneously.
Hi Am new to Jquery/ajax and need help with the final (I think) piece of code.
I have a draggable item (JQuery ui.draggable) that when placed in a drop zone updates a mysql table - that works, with this:
function addlist(param)
{
$.ajax({
type: "POST",
url: "ajax/addtocart.php",
data: 'img='+encodeURIComponent(param),
dataType: 'json',
beforeSend: function(x){$('#ajax-loader').css('visibility','visible');}
});
}
but what I cannot get it to do is "reload" another page/same page to display the updated results.
In simple terms I want to
Drag & drop
Update the database
Show loading gif
Display list from DB table with the updated post (i.e. from the drag & drop)
The are many ways of doing it. What I would probably do is have the PHP script output the content that needs to be displayed. This could be done either through JSON (which is basically data encoded in JavaScript syntax) or through raw HTML.
If you were to use raw HTML:
function addlist(param)
{
$.ajax(
{
type: 'POST',
url: 'ajax/addtocart.php',
data: 'img=' + encodeURIComponent(param),
dataType: 'html',
beforeSend: function()
{
$('#ajax-loader').css('visibility','visible');
},
success: function(data, status)
{
// Process the returned HTML and append it to some part of the page.
var elements = $(data);
$('#some-element').append(elements);
},
error: function()
{
// Handle errors here.
},
complete: function()
{
// Hide the loading GIF.
}
});
}
If using JSON, the process would essentially be the same, except you'd have to construct the new HTML elements yourself in the JavaScript (and the output from the PHP script would have to be encoded using json_encode, obviously). Your success callback might then look like this:
function(data, status)
{
// Get some properties from the JSON structure and build a list item.
var item = $('<li />');
$('<div id="div-1" />').text(data.foo).appendTo(item);
$('<div id="div-2" />').text(data.bar).appendTo(item);
// Append the item to some other element that already exists.
$('#some-element').append(item);
}
I don't know PHP but what you want is addtocart.php to give back some kind of response (echo?)
that you will take care of.
$.ajax({
type: "POST",
url: "ajax/addtocart.php",
data: 'img='+encodeURIComponent(param),
dataType: 'json',
beforeSend: function(x){$('#ajax-loader').css('visibility','visible');
success: function(response){ /* use the response to update your html*/} });