I am trying to lookup an employee by their ID using a jQuery modal. My Modal has an input text box for the employee ID and a Search button. Once the search button is clicked I have the value looked up in a db and if no result exists I am looking for an error message to display on that same modal.
My controller looks like this:
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("CreateEmpLookup")]
public ActionResult CreateEmpLookupPost(string empIDSearch)
{
List<spGetEmployeeDataByEIDResult> res = new List<spGetEmployeeDataByEIDResult>(_service.GetUserFromDB(empIDSearch));
if (res.Count > 0)
{
ViewData["Status"] = true;
return RedirectToAction("Create", new { empID = empIDSearch });
}
else
{
ViewData["Status"] = "false";
return Content("False");
}
}
I'm just not sure how to relay the information back to the pop up modal that there is no result. I'm thinking I have to replace this line return Content("False"); with the message that will go back to the jQuery pop up modal.
In my pop up modal I have the following line that will display any error messages:
<input type="hidden" id="Status" value="<%= (ViewData["Status"] == null) ? "true" : ViewData["Status"].ToString() %>" />
Here is a snippet of my jQuery code:
$('#login_form').modal();
And the div that jQuery targets:
<div id="login_form" style='display: none'>
<div id="status" align="left">
<center>
<h1>
<img src="../../Content/modal_images/Search48.png" alt="Key" id="modal_img" />
<label id="modal_title">
Employee Search</label>
</h1>
<br class="modal_br" />
<div id="login_response">
<input type="hidden" id="Status" value="<%= (ViewData["Status"] == null) ? "true" : ViewData["Status"].ToString() %>" />
</div>
</center>
<% using (Html.BeginForm("CreateEmpLookup", "", FormMethod.Post))
{ %>
<form id="login" action="javascript:alert('success!');">
<%--<input type="hidden" name="action" value="user_login" />
<input type="hidden" name="module" value="login" />--%>
<table class="modal_table">
<tr>
<td>
<label id="modal_label">
Employee ID:</label>
</td>
<td>
<%= Html.TextBox("empIDSearch", "", new { #maxlength = "6" })%>
</td>
</tr>
<tr>
<td>
</td>
<td>
<input value="Search" name="Search" id="submit" type="submit" />
<div id="ajax_loading">
<img src="../../Content/modal_images/spinner.gif" alt="Processing" /> Processing...
</div>
</td>
</tr>
</table>
</form>
<% } %>
</div>
</div>
Any advice on how to make this easier or fix this problem would really help.
Thank you.
#GB, I can think of a couple of ways to do this. However, given you are using a Modal dialog and you want to display it in there that kinda limits your options.
If you're doing a post using a submit button, as it looks like you are, then on return back to the page you need to display the popup again and then fill in the details.
One nifty way of doing that might be to use PartialViews (PV). If you get back a result then you could render on PV and if not then you render another one. Not great but it would work.
The best way, IMHO, is to use jQuery to do a partial postback. Then you could do your search and on return from the partial post back you could render either a list or the error.
So;
Allow user to enter the search
criteria
Do a jQuery/AJAX call to do your
search
If you fail, then return a PV that
contains your error and render that
to a parent DIV.
If you succeed, and it's not clear
what you're doing at this point,
show another PV with the user
details / List.
An AJAX postback can return a PV. The return value in this case is html that can simply be inserted into a Div or something.
This would be ideal as you don't get the annoying screen flicker effect.
If you want code samples, post a comment and I'll provide some.
Related
I have an issue when changing my asp.net webforms project to semantic UI. Below is one of my forms; when I click the submit button, it triggers an event handler server-side, but I get an empty string instead of what I have input to textbox.
Link that call modal:
Recover Password
Modal's HTML :
<div class="ui small modal" id="recovermodal">
<form class="ui large form" runat="server">
<i class="close icon"></i>
<div class="header">
RECOVER PASSWORD
</div>
<div class="content">
<div class="description">
<div class="field">
<label>E-MAIL</label><%--
<input type="text" name="rev-email" placeholder="E-MAIL">--%>
<input type="text" ID="txtRP_Email" name="rev-email" runat="server" placeholder="E-MAIL" />
</div>
<div class="field">
<label>PHONE NUMBER</label><%--
<input type="text" name="rev-phone" placeholder="PHONE NUMBER">--%>
<input type="text" ID="txtRP_MobileNo" name="rev-phone" placeholder="PHONE NUMBER" runat="server" />
</div>
<div class="custommodalfooter">
<div class="ui reset button offmodal">DISCARD</div>
<asp:LinkButton ID="btnRecoverPassword" runat="server" CssClass="ui green submit right labeled icon button" onclick="dorecover_Click">
<%= base.GetLocalText("html_buttonConfirm")%>
</asp:LinkButton>
<!-- <button class="ui reset button offmodal">DISCARD</button><button class="ui positive right labeled icon button" type="submit"><i class="right arrow icon"></i>
CONFIRM
</button> -->
</div>
</div>
</div>
</form>
</div>
Server side :
Here is where I get Email and MobileNo as empty string
protected void dorecover_Click(object sender, EventArgs e)
{
String Email = txtRP_Email.Value.Trim();
String MobileNo = txtRP_MobileNo.Value.Trim();
}
Please try to get your values from Request.Form.
protected void dorecover_Click(object sender, EventArgs e)
{
String Email = Request.Form.Item["txtRP_Email"].Trim();
String MobileNo = Request.Form.Item["txtRP_MobileNo"].Trim();
}
Maybe there is some conversion to string type is needed before using Trim(). I had no chance to test this code, but in theory this is what you need.
You aren't showing everything, but undisplayed (visible:none) fields are not posted. When the "approve" (ok) button of the dialog is clicked, it may be setting the visibility of the dialog to "none" before the form is posted.
If you handle the onApprove callback of the dialog and return false, that may solve the problem as returning false keeps the modal from hiding.
However, you may need to call dorecover_Click from the onapprove handler itself instead of having it directly on the button if the postback is called before the onApprove handler.
See this question to get you started in the right direction:
Stack Overflow: Calling an ASP.NET EventHandler from JavaScript
Try this :
$('#your-modal-id').modal({ useFlex: false}).modal("show");
$('.ui.dimmer.modals').appendTo('#aspnetForm');
$('.ui.dimmer.modals').css('overflow', 'scroll');
$('#your-modal-id').css('position', 'relative');
So in my MVC Orchard application the user chooses a location from a DD & selects a date from a datepicker. Search then looks through the DB table and returns a list of results (if any). User can then use the 'View' button to view each record on screen. This all works fine, however if the user presses the 'back' button, after viewing the record I get the error:
Webpage has expired
I've looked through other examples of GET and POST in my code and I can see no diff. does anyone have any idea why this is happening, think it is something to do with the search, please see code below
#model Project.ViewModels.SearchDeliveryRunsVM
#{
Script.Require("ShapesBase");
Layout.Title = T("Delivery Runs History").ToString();
Script.Require("jQuery");
Script.Require("jQueryUI");
Style.Require("jQueryUI_DatePicker");
}
#using (Html.BeginFormAntiForgeryPost())
{
<div>
<div style="display:inline-block">
<div class="editor-label">Delivery Run</div>
<div class="editor-label">#Html.DropDownList("DeliveryRunId", Model.DeliveryRunList)</div>
</div>
<div style="display:inline-block">
<div class="editor-label">#T("Date")</div>
<div class="editor-label">#Html.TextBoxFor(model => model.SelectedDate, new { #class = "jquery_datepicker", #Value = Model.SelectedDate.HasValue ? Model.SelectedDate.Value.ToString("dd/MM/yyyy") : string.Empty })</div>
</div>
<button style="display:inline-block" type="submit">#T("Search")</button>
</div>
if (Model.Orders != null && Model.Orders.Count() > 0)
{
<br />
<table class="items">
<colgroup>
<col id="Col10" />
<col id="Col11" />
</colgroup>
<tr>
<th>Order Id</th>
<th>Customer</th>
<th>Value</th>
<th>Payment</th>
<th>Signature</th>
<th></th>
</tr>
#foreach (Project.Models.OrderInfo results in Model.Orders)
{
<tr>
<td>#results.OrderRecordId</td>
<td>#results.QbCustName</td>
<td>#results.Value</td>
<td>#results.Payment</td>
<td>#Html.CheckBoxFor(x => results.Signature, new { disabled = "disabled" })</td>
<td>
<div>
#T("ViewOrder")
</div>
</td>
</tr>
}
</table>
}
else
{
if (!Model.IsInitialGet)
{
<p>No records exist</p>
}
}
}
#using (Script.Foot())
{
<script type="text/javascript" language="javascript">
$(function () {
var dates = $("#SelectedDate").datepicker({
dateFormat: 'dd/mm/yy'
}).val("#(Model.SelectedDate.HasValue ? Model.SelectedDate.Value.ToString("dd/MM/yyyy") : DateTime.Now.ToString("dd/MM/yyyy"))");
});
</script>
}
UPDATE
All the other search features on my site are using the Index function of each controller, then in the view using something like:
#using(Html.BeginForm("Index", "CustomerAdmin", FormMethod.Get)) {
<fieldset class="bulk-actions">
<label for="search">#T("Search:")</label>
#Html.TextBoxFor(m => m.SearchExpression)
<button type="submit">#T("Search")</button>
#T("Clear")
</fieldset>
}
to use the GET to display the results, where as my problem I am using GET and POST. perhaps?
It is normal that a page created by a POST action expires after the page is navigated away from; you wouldn't, for example, want the back button to trigger a second credit card charge attempt... You could try using output caching
View:
#using (#Html.BeginForm("Show", "test", FormMethod.Post))
{
<fieldset>
<table >
<tr>
<td>
#Html.LabelFor(model=> model.Show)
</td>
<td>
#Html.TextBox("txtvalue", null)
</td>
</tr>
</table>
<input type="button" value="Show" onclick = "#("location.href='"+ #Url.Action("Show", "test")+"'" )" />
<input type="button" value="Go" onclick ="#("location.href='"+ #Url.Action("Go", "test")+"'" )"/>
</fieldset>
}
and two action methods in the controller,
public ActionResult Show(string txtvalue)
{
...
}
public ActionResult Go(string txtvalue)
{
...
}
based on which button been click , it should go to the corresponding action method and pass the value of the textbox.
Can anyone suggest me the way to do it. I wrapping my head around couldn't figure out.
Try this,
<input type="button" value="Show" onclick = "location.href='#Url.Action("Show", "Foo")'"/>
<input type="button" value="Go" onclick = "location.href='#Url.Action("Go", "Foo")'"/>
UPDATE:
As type="button" does not submit the values in the form, its not directly possible to do what you have asked, the better idea is to Identify the Button that has been clicked in the controller method as show in this link
Try this
<input type="button" value="Show" onclick="location.href='<%: Url.Action("Show", "Controller") %>'" />
<input type="button" value="Go" onclick="location.href='<%: Url.Action("Go", "Controller") %>'" />
Try something like:
<input type="button" value="Show" onclick="location.href='<%:Url.Action("Show", "ControllerName")%>'"/>
<input type="button" value="Go" onclick="location.href='<%:Url.Action("Go", "ControllerName")%>'"/>
If you are posting more form data you can use Ajax, see Making a Simple Ajax call to controller in asp.net mvc
I have the following partial view.
#using System.Data;
#using System.Dynamic;
#using System.Collections.Generic;
#using System.Linq;
#model TheMProject.Models.MyViewModel
<div id="Item_Buttons">
<h2 class="alignleft">Table 1</h2>
<p class="alignright">Item Name<input type="text" name="item_name" value="#Html.ValueFor(x => x.itemname)" class="search-query" placeholder="Search" style ="width:100px"/>
<button class="btn btn-success" id="Change_Item_Name" value="Change_Item_Name" name="action:Change_Item_Name" type="button"> Change Item Name</button>
Grade<input type="text" name="item_grade" value="#Html.ValueFor(x => x.grade)" class="search-query" placeholder="Search" style="width:100px"/>
<button class="btn btn-success" id="ChangeItemGrade" value="ChangeItemGrade" name="action:Change_Grade" type="button">Change Grade</button>
Delete Record<input type="text" name="delete_item" value="#Html.ValueFor(x => x.itemname)" class="search-query" placeholder="Search" style ="width:100px"/>
<button class="btn btn-success" id="DeleteItem" value="DeleteItem" name="action:Delete_Item" type="button">Delete Record</button>
</p>
<div style="clear: both;"></div>
</div>
<section>
<div id ="firstgrid">
<table id="TTable" class="gridTable">
<thead class="gridHead">
<tr>
#Html.DisplayFor(x => x.TColumns)
</tr>
</thead>
<tbody>
#Html.DisplayFor(x => x.TRows)
</tbody>
</table>
</div>
</section>
<section>
<form id="form1">
<div id="grid">
<table id="CTable" class="gridTable">
<thead class="gridHead">
<tr>
#Html.DisplayFor(x => x.Columns)
</tr>
</thead>
<tbody>
#Html.DisplayFor(x => x.Rows)
</tbody>
</table>
</div>
</form>
</section>
<section>
<div id ="Display_Average">
<table id="AvgDisplayTable" class="gridTable">
<thead class="gridHead">
<tr>
#Html.DisplayFor(x => x.AvgColumns)
</tr>
</thead>
<tbody>
#Html.DisplayFor(x => x.AvgRows)
</tbody>
</table>
</div>
</section>
<button class="btn" id="SubmitAverage" value ="SubmitAverage" name="action:SubmitAverage" type="button">Submit Averages</button>
<div id="ItemNameDiv" title="Change Item Name">
#using (Html.BeginForm("ChangeItemName", "Home", "POST"))
{
<section>
Heat Name:<input type="text" name="itemName" value="#Html.ValueFor(x => x.heatname)" style ="width:100px"/>
Change to:<input type="text" name="updatedName" value="" style="width: 100px" />
<input type="button" id="ChangeItemName" name="ChangeItemName" value="Change" />
</section>
}
</div>
<div id="ItemGradeDiv" title="Change Item Grade">
#using (Html.BeginForm("ChangeGrade", "Home", "POST"))
{
<section>
Item Grade:<input type="text" name="grade" value="#Html.ValueFor(x => x.grade)" style ="width:100px"/>
Change to:<input type="text" name="updatedName" value="" style="width: 100px" />
<input type ="hidden" name="hiddenItem" value ="#Html.ValueFor(x => x.itemname)" />
<input type="submit" name="ChangeGrade" value="Change" />
</section>
}
</div>
<div id="DeleteItemDiv" title="Delete Item">
#using (Html.BeginForm("DeleteItem", "Home", "POST"))
{
<section>
Heat Name:<input type="text" name="itemName" value="#Html.ValueFor(x => x.itemname)" style ="width:100px"/>
<input type="submit" name="DeleteItem" value="Delete" />
</section>
}
</div>
When the Change Item Name button is clicked, an ajax post is called with jquery as seen here:
$(document).ready(function () {
$('#ChangeItemName').click(function (e) {
var tdata = $('#form1').serialize();
var origname = $('#ItemNameDiv').find('input[name="itemName"]').first().val();
var newname = $('#ItemNameDiv').find('input[name="updatedName"]').first().val();
$.ajax({
type: "POST",
data: {
mCollection: tdata,
itemName: origname,
updatedName: newname
},
url: "Home/ChangeItemName",
success: function (result) { success(result); }
});
});
function success(result) {
$('#ItemNameDiv').dialog('close');
$("#My_Partial_V").html(result);
}
});
. Upon completion, the partial view is refreshed with the updated data from the post. Including the jquery required for this post, there are other scripts required to perform other actions in the view such as hiding the divs shown below the submit average button until other buttons are clicked. After the first time the previously mentioned ajax post is performed, if the same button is clicked the post is called twice instead of once, the third time its clicked it runs 4 times, etc.
Ive tried moving the script reference
<script src="#Url.Content("~/Scripts/partialitemscripts.js")"
type="text/javascript"></script>
outside of the partial view and into the view which contains the partial as well as into the layout file. When I try these two methods everything loads correctly until the partial view is refreshed at which time all the scripts fail to be called/referenced.
You could try to move the script outside of the Partialview and into the mainview (like you said), but change it a little: instead of triggering the function when the document is loaded, put it all in a function:
function ajaxCallback(result){
$('#ChangeItemName').click(function (e) {
var tdata = $('#form1').serialize();
var origname = $('#ItemNameDiv').find('input[name="itemName"]').first().val();
var newname = $('#ItemNameDiv').find('input[name="updatedName"]').first().val();
$.ajax({
type: "POST",
data: {
mCollection: tdata,
itemName: origname,
updatedName: newname
},
url: "Home/ChangeItemName",
success: function (result) { success(result); }
});
});
}
Then you call this function from the ready event of your main view (the one that contains the partial).
To fix your button not working anymore when you've done an ajax request you've got to update your success-function to call the ajaxCallback (this would be in the partialitemscripts.js together with the ajaxCallback function):
function success(result) {
$('#ItemNameDiv').dialog('close');
$("#My_Partial_V").html(result);
ajaxCallback();
}
I'm not sure it this is the ideal solution, but I managed to get something similar working this way.
Although it is hard from the code posted to make sure. It seems that the reason the scripts fail after the first time is because you use the .html() which adds elements to the DOM and the click() event has not been binded to those new elements.
In this case you should use on() or delegate(). See the jquery documentation for how to use those. It is simple.
In my web page, I need to populate button according to parameter value called ButtonType.
let's say that If ButtonType == "Edit" then I need to hide every buttons but butUpdate.
I want to know how to show/hide html buttons via MVC Action method.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SupplierDetail(int SupplierID, string ButtonType)
{
var Supplier = supplierListRepository.Supplier_SelectByID(SupplierID);
return View(Supplier);
}
I am using Asp.net Mvc Razor form.
#using (Html.BeginForm("SupplierDetail_SubmitClick", "Supplier", FormMethod.Post, new { id = "frmSupplierDetail" }))
{
#Html.ValidationSummary(true)
<table cellpadding="0" cellspacing="0" border="0" style="width:450px; height:auto">
.....
<tr>
<td>#Html.LabelFor(model => model.Phone)</td>
<td>#Html.EditorFor(model => model.Phone)
#Html.ValidationMessageFor(model => model.Phone)</td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>
<input type="submit" id="butSave" name="butSave" value="Save" style="width:100px; height:auto" />
<input type="submit" id="butUpdate" name="butUpdate" value="Update" style="width:100px; height:auto" />
<input type="submit" id="butDelete" name="butDelete" value="Delete" style="width:100px; height:auto" />
<input type="submit" id="butReset" name="butReset" value="Reset" style="width:100px; height:auto" />
</td>
</tr>
</table>
</div>
<div id="content">
#Html.ActionLink("Back to List", "Index")
</div>
}
Every Suggestions will be appreciated.
It is not a controller action responsibility to show/hide buttons. A controller action doesn't/shouldn't even know what a button means. That's a concept that exists on the view. A controller action on the other hand is supposed to communicate with the model and prepare a view model that it passes to the view for displaying. So you could define a view model that will contain properties defining the visibility of the buttons and based on the value of the ButtonType parameter set those properties accordingly. Then the controller action will pas this view model to the view instead of the supplier object that you are currently passing. Obviously the view model will also have a property to hold this supplier. Now all that's left for the view is based on the values of the view model properties decide how to display the buttons.
in your controller add the buttontype to viewdata:
ViewData["ButtonType"] = ButtonType
Then, in the view itself, you can add if/else statements, or any other logic that suits all of ur cases, to decide what to render:
#if (ViewData["ButtonType"].ToString() == "Edit")
{
<input type="submit" id="butUpdate" name="butUpdate" value="Update"
style="width:100px; height:auto" />
}
Of course, this is but a demo of what can be done, Yuo should adapt the code to ur buisness logics