Event not firing on button click event - c#

This is a problem I haven't come across before.
I'm working on an MVC4 project. I'm using an asp button control because there isn't a Html Helper that can be used for a button (re: There's no #Html.Button !). My button code is:
<td><asp:Button ID="ButtonUndo" runat="server" Text="Undo"
OnClick="ButtonUndo_Click" AutoPostBack="true"/></td>
I went to the Designer tab and clicked on this button which produced the event handler:
protected void ButtonUndo_Click(object sender, EventArgs e)
{
RRSPSqlEntities db = new RRSPSqlEntities();
int id = (int)ViewData["ClientId"];
var updateAddress = (from a in db.Address
where a.PersonId == id
select a).SingleOrDefault();
updateAddress.Deleted = false;
db.SaveChanges();
}
I should add that this code was added to the same .aspx page wrapped in a script tag. Also within this section is the Page_Load method. The eventhandler is not within Page_Load.
The problem was found when I set a breakpoint and stepped through the code. Clicking my button shows that it doesn't hit my event handler at all. I don't know why this is, particularly as ASP created the event from clicking the button in Design mode.

Clicking my button shows that it doesn't hit my event handler at all.
This isn't all that surprising. ASP.NET MVC uses a completely different event model (i.e. it doesn't have one like web forms). However, what you're trying to do is very straight forward. In your controller build a new method, let's call it Undo:
public ActionResult Undo(int id)
{
RRSPSqlEntities db = new RRSPSqlEntities();
var updateAddress = (from a in db.Address
where a.PersonId == id
select a).SingleOrDefault();
updateAddress.Deleted = false;
db.SaveChanges();
return View("{insert the original action name here}");
}
and then in your markup, simply markup the input like this:
<form method="POST" action="/ControllerName/Undo">
#Html.HiddenFor(Model.Id)
<input type="submit" value="Undo" />
</form>
where the Model for the View you're on contains a property, I've called it Id, that is the id you want passed into Undo.

I usually prefer to make ajax calls. You can try:
<button type="button" class="button" onclick="ButtonUndo();" />
In the form:
<script>
function ButtonUndo() {
$.ajax({
type: 'POST',
url: '/controller/action',
data: 'PersonID=' + ID,
dataType: 'json',
cache: false,
success: function (result) {
//do stuff here
},
error: function () {
//do error stuff here
}
});
}
</script>
Controller:
[HttpPost]
public ActionResult Action(int PersonID)
{
//Do your stuff here
return new JsonResult { result = "something" };
}
(Sorry for any typos or syntax errors...I pulled from existing code that we use in a project.)

Related

Render part of page on dropdown selection part 2

This is a follow on to similar question but taking suggestions into account.
Render part of page on dropdown selection
I have a chart on my main view which I would like to update partially when a dropdown selects different values.
The page renders correctly the first time, but when I select a new value in the dropdown, then I think the .submit script is failing in the script .submit() because when I put a break on window.submitAjaxForm it is never reached.
_PnlChart.cshtml
<img src="#Url.Action("CreateTraderPnlChart3")" width="600" height="600" align="middle" vspace="50" />
My mainview Index.cshtml:
<div class="w3-half">
<div id="ExportDiv">
#{ Html.RenderPartial("_PnlChart");}
</div>
#using (Ajax.BeginForm("GetEnvironment",
new RouteValueDictionary { { "Environment", "" } }, new AjaxOptions() { UpdateTargetId = "ExportDiv" }, new { id = "ajaxForm" } ))
{
#Html.DropDownList("PeriodSelection",
new SelectList((string[])Session["Periods"]),
(string)Session["Period"],
new
{ onchange = "submitAjaxForm()" })
}
</script>
<script type="text/javascript">
$('form#ajaxForm').submit(function(event) {
eval($(this).attr('onsubmit')); return false;
});
window.submitAjaxForm = function(){
$('form#ajaxForm').submit();
}
</script>
</div>
My controller:
public ActionResult PeriodSelection(string dropdownlistReturnValue) // dont know what dropdownlistReturnValue is doing?
{
Session["Period"] = dropdownlistReturnValue;
return PartialView("~/Views/Employee/_PnlChart.cshtml");
}
This line in your code,
eval($(this).attr('onsubmit')); return false;
I am not sure what you were intending to do here. But from your question, i assume you wanted to do a form submission. But that line will not submit the form. The expression $(this).attr('onsubmit') is going to return undefined as your form does not have an onsubmit attribute defined.
But you already have the form submit code in your other method (submitAjaxForm). So if you simply remove the $('form#ajaxForm').submit handler (apparently it does not do anything useful), your code will work. When you change the dropdown, it will make an ajax form submission.
But your form action is set to GetEnvironment action method. That means your ajax form submission will be to that action method. In your question you have a different action method which returns the updated chart content. It does not makes sense!
I personally prefer to write handwritten ajax calls instead of relying on the ajax action helper methods. The below is the code i would probably use (Except the dropdownlist code. read further)
<div id="ExportDiv">
#{ Html.RenderPartial("_PnlChart");}
</div>
#Html.DropDownList("PeriodSelection",
new SelectList((string[])Session["Periods"]),
(string)Session["Period"], new
{ data_charturl = Url.Action("PeriodSelection","Home")})
Now listen to the change event of the SELECT element.
$(function(){
$("#PeriodSelection").change(function(){
var v = $(this).val();
var url=$(this).data("charturl")+'?dropdownlistReturnValue='+v;
$("#ExportDiv").load(url);
});
});
You should consider using the a view model to pass the Dropdownlist data. Why not use the DropDownListFor helper method ? It looks much clean, Mixing a lot of C# code (See all the session casting and all.) makes it kind of dirty IMHO.

Render a new partial view on existing partial view

I am trying to do a drill down report. I am using MVC and Devexpress Gridviews. I render my view and the partial view and display my gridview with the result.
Now what I need to accomplished is when I double click on the gridview I need to render a new/different partial view in the place off the existing gridview - The one I double clicked on.
Is this possible?
Here is what I have:
public ActionResult MainPartial()
{
using (var Context = new DataContext())
{
ViewBag.Level = 0;
return PartialView("MainPartial",SomeData);
}
}
public ActionResult FirstDrilldownPartial(int Param)
{
using (var Context = new DataContext())
{
ViewBag.Level = 1;
return PartialView("FirstDrilldownPartial",SomeNewData(Param));
}
}
My Gridview RowDblClick event
function onDoubleClick(s, e) {
$.ajax({
type: 'POST',
url: '/Controler/FirstDrilldownPartial',
dataType: 'json',
async: false,
//cache: false,
data: {
Param: 1
}
});
}
At the moment everything is working but when I call the function "function onDoubleClick(s, e)" the Main grid stay on the view and the new grid is not rendered.
Can someone please help with suggestions.
Thanks
You can render both partials in different divs and hide or show in your js function a div, for example
<div id="mydiv1">
#Html.Partial("Partial1")
<div>
<div id="mydiv2">
#Html.Partial("Partial2")
</div>
and in your onDoubleClick ( I assume that you are using jQuery)
$("#mydiv1").hide();
$("#mydiv2").show();
and to hide (on page load) the second div first just add
$(function () {
$("#mydiv2").hide();
});
or use
<div id="mydiv2" style="display:none;">
This code is not tested, but it should work.

Doing a postback without AutoPostBack

I've got a WebForm with two drop down lists, where the contents of the second one depend on the first.
So if the user changes the category, the second dropdown needs to be filled with the list of subcategories.
This sounds like a typical job for AutoPostBack.
However, there's a bit of a problem with AutoPostBack: if the list isn't dropped open, and the user uses the keyboard to make the choice, the postback happens right after the first keystroke. This prevents the user from scrolling down the list with the down arrow, or typing the name of the category.
This happens in Chrome and IE and Opera, but not in Firefox. Firefox fires the onchange event only when leaving the control (tabbing to the next control), just like it would when the list was dropped open, and that's what I want the other browsers to do too.
Any solutions how I can achieve this?
I tried to remove the AutoPostBack attribute and use onblur, but apparently the page works differently with AutoPostBack than without, because the browsers start complaining about Javascript errors.
Now since we're all so fond of jsFiddle, here's one. It doesn't actually do anything, but it can demonstrate the problem. Click on the first dropdown, then click again to close the list. (This is what happens when you navigate through the form with the tab key: dropdown lists don't open up.) Now type a letter or the down arrow. Firefox changes the current selection and waits for you to do anything else, but Chrome and IE and Opera all attempt to submit the form immediately, with drastic results.
So how can I avoid that? And note that simply changing the fiddle may not be enough, it must be translatable back to an ASP.NET solution.
Ok here is how I'd do it by using ajax and avoiding the use of AutoPostback all together to populate my sub category.
Create an object that represents the select list json object to send back.
public class SelectItem
{
public string Id { get; set; }
public string Text { get; set; }
}
Then create a PageMethod:
[WebMethod]
public static List<SelectItem> GetSubCategories(string Id)
{
// Returning dummy data for demo purposes
var subCats = new List<SelectItem>();
if (Id == "1")
{
subCats.Add(new SelectItem { Id = "1", Text = "1 Subs"});
}
else if (Id == "2")
{
subCats.Add(new SelectItem { Id = "2", Text = "2 Subs"});
}
return subCats;
}
Add a script manager and EnablePageMethods i.e.
<asp:ScriptManager runat="server" EnablePageMethods="true">
</asp:ScriptManager>
Change your dropdown lists to use ClientIDMode="Static"
<asp:DropDownList Id="ddlCategory" runat="server" ClientIDMode="Static">
<asp:ListItem Value ="1" Text ="One"></asp:ListItem>
<asp:ListItem Value ="2" Text ="Two"></asp:ListItem>
</asp:DropDownList>
<asp:DropDownList Id="ddlSubCategory" runat="server" ClientIDMode="Static">
</asp:DropDownList>
Then use the following jQuery:
<script type="text/javascript">
$(function () {
var $cat = $('#ddlCategory');
$cat.click(function () {
var catId = $cat.val();
$.ajax({
type: "POST",
url: "Default.aspx/GetSubCategories",
data: "{ Id: " + catId + " }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var subs = msg.d;
// empty selection
var $ddlSubCategory = $('#ddlSubCategory');
$ddlSubCategory.empty();
$.each(subs, function (index, sub) {
$ddlSubCategory.append($('<option/>', {
value: sub.Id,
text: sub.Text
}));
});
}
});
});
});
</script>

JQuery autocomplete combobox selecting from one repopulates another

I have an ASP.NET web app that is using JQuery autocomplete to build a nice dynamic combobox. One of the boxes on the page fires a change event that reloads another box. Basically like a UserGroup / Members scenario. My change event fires and repopulates the underlying select box, I then do a remove on the input and button that build the combobox - which all work great up to this point. My last line is to call the combobox method on the newly repopulated select which doesn't seem to fire ? The standard select shows with the new data but no JQuery Goodness. Any help is appreciated. Thanks.
On Change Event:
function GetAnalysts() {
$.ajax({
type: "POST",
url: "GetAnalystByGroup.ashx",
data: 'group=' + $("#<%=supportGroup.ClientID%>" + " option:selected").text(),
success: function (response) {
var analysts = eval(response);
$("#<%=assignedAnalyst.ClientID%>").children().remove();
$("#<%=assignedAnalyst.ClientID%>").append($('<option></option>').val('').html(firstoption));
for (var i = 0; i < analysts.length; i++) {
var text = analysts[i]['label'];
var val = analysts[i]['upn'];
$("#<%=assignedAnalyst.ClientID%>").append($('<option></option>').val(val).html(text));
}
//remove the JQ Combo then rebuild it
$("#<%=assignedAnalyst.ClientID%>JQ").remove();
$("#<%=assignedAnalyst.ClientID%>JQBut").remove();
$("#<%=assignedAnalyst.ClientID%>").show();
$("#<%=assignedAnalyst.ClientID%>").combobox();
},
error: function () {
}
});
}
I ended up working around the problem by coding the remove/show lines into a javascript pageload event and moving the AJAX call inside an update panel.

Prevent scrolling to top using .load()

I'm trying to prevent the scrolling to the top when using jQuery's .load function. I've read at SO that you can use event.preventDefault(); event.stopPropagation();. Here is the link to this question. But when using beginform, you don't have an event here.
I also tried to put a click event on the submit button, but this also didn't work.
Thanks in advance!
This is the code of the view. When success the function closeFancyReservationCancel is called.
#using (
Ajax.BeginForm("Cancel",
"Reservation",
new AjaxOptions { HttpMethod = "POST",
OnSuccess = "closeFancyReservationCancel"},
new { id = "cancelForm" }))
{
...
}
)
And this is the jQuery function
function closeFancyReservationCancel() {
$.fancybox.close();
$('#reservationList').load(ResolveUrl('~/Reservation/reservationList'));
}
function ResolveUrl(url) {
if (url.indexOf("~/") == 0) {
url = baseUrl + url.substring(2);
}
return url;
}
Here a part of my HTML:
<div id="reservationList" class="tblContainer">
#Html.Action("reservationList", "Reservation")
</div>
The action reservationList returns a view with the table. Only the body of the table has an overflow: auto;.
EDIT: added more information
I have a div with a list of my reservations table. I am using MVC3 to show that list. When press the cancel button, the div will reload by the .load function.
EDIT
Here my HTML view with the table:
Pastebin
You can simply get the Scroll amount before loading. And apply the same scroll amount after load is finished
function closeFancyReservationCancel() {
$.fancybox.close();
var scroll_amount= $('#reservationList').scrollTop();
$('#reservationList').load(ResolveUrl('~/Reservation/reservationList'),
function() {
$('#reservationList').scrollTop(scroll_amount);
});
}
If you want you can also use .scrollLeft() amount.

Categories