Ajax form: OnSuccess, load partial div - javascript

I have this Ajax Form
#using(Ajax.BeginForm("AddAttendeeManual", "Attendee", new AjaxOptions { HttpMethod = "POST", OnSuccess = "doneManualEmail" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-group">
#Html.TextBoxFor(m => m.SelectedManualEmail.Email, new {#class = "form-control",PlaceHolder="Email"})
</div>
<input type="submit" id="btnManual"class="btn btn-default" value="Add>>" />
}
and a div, both are on same view
<div id="invitedPeoples" data-url="#Url.Action("InvitedAttendees", "Attendee", new { appointmentId = Model.AppointmentId })">
</div>
Everytime the form is submitted, I wanted to load the div that should have a partial view.
This is what I have done
function doneManualEmail(isRequestSucceded) {
$(#Html.IdFor(m=>m.SelectedManualEmail.Email)).val('');
var url = $("#invitedPeoples").data('url');
$.get(url, function (data) {
$('#invitedPeoples').html(data);
});
};
everytime the form is submitted, i get forwarded to InvitedAttendees method, but my partial view doesn't show up.
The first line of the jquery works fine but the part to load partial view doesn't work.
Any thing I'm missing?
Error in Console:

Related

asp.net mvc Ajax.BeginForm duplicating elements

I am using ajax to load data using partial view and at the same i have implemented search functionality. Its working fine but when i keep my search textbox empty and then hit search button then my layout gets duplicated.
here is my code
controller :
public async Task<ActionResult> Index(string search)
{
if (!Request.IsAjaxRequest())
return View(await _employeeRepository.GetAllEmployeesAsync());
if (string.IsNullOrEmpty(search))
return View(await _employeeRepository.GetAllEmployeesAsync());
return PartialView("_EmployeeList",(await _employeeRepository
.GetAllEmployeesAsync())
.Where(x =>x.EmployeeName.StartsWith(search,
StringComparison.OrdinalIgnoreCase)));
}
Index.cshtml
#model IEnumerable<MvcDemo.Models.Employee>
#using (Ajax.BeginForm("Index", "Employee", new AjaxOptions
{
OnFailure = "record not loaded",
HttpMethod = "GET",
UpdateTargetId = "employeeData",
InsertionMode = InsertionMode.Replace
}))
{
<input type="text" name="search"
class="form-control"
placeholder="search by name..."/>
<input type="submit" value="Search"/>
}
<div id="employeeData">
#Html.Partial("_EmployeeList", Model);
#* i have used render partial as well*#
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryajax")
}
BundleConfig:
bundles.Add(new ScriptBundle("~/bundles/jqueryajax").Include(
"~/Scripts/jquery.unobtrusive-ajax.min.js"));
Layout.cshtml :
#Scripts.Render("~/bundles/jqueryajax")
Can anybody tell me where i am going wrong ? Keeping the input blank and clicking on search button duplicating the layout.
Take a look at my screenshot screen 1 screen 2 screen 3
Any help would be much appreciated.
If search text is null or empty, you are returning the index view, instead of this return partial view.
if (string.IsNullOrEmpty(search))
return PartialView("_EmployeeList", (await _employeeRepository.GetAllEmployeesAsync()));

Dynamically adding Partial View using Ajax

I have created a partial view where i am using Bootstrap Glyphicon (collapse and expand) upon button click. But, the JavaScript code is not working here as I am
dynamically adding Partial View using Ajax.
My Controller:
public ActionResult DisplaySearchResults(int Id)
{
if (Id == 317)
{
return PartialView("~/Views/Shared/_PartialReportViews/StatisticalReport.cshtml");
}
else if (Id == 318)
{
return PartialView("~/Views/Shared/_PartialReportViews/Leading_Progeny.cshtml");
}
return PartialView();
}
My main View:
<div class="container">
<div id="partial"></div>
#section scripts{
<script type="text/javascript">
$('.search').click(function () {
var id = $(this).data('assigned-id');
var route = '#Url.Action("DisplaySearchResults", "Home")?id=' + id;
$('#partial').load(route);
});
var partial = $('#partial');
partial.on('shown.bs.collapse', '.collapse', function () {
$(this).closest('.group').find(".glyphicon-plus").removeClass("glyphicon-plus").addClass("glyphicon-minus");
}).on('hidden.bs.collapse', '.collapse', function () {
$(this).closest('.group').find(".glyphicon-minus").removeClass("glyphicon-minus").addClass("glyphicon-plus");
});
</script>
}
<input class="search btn-info" type="button" value="Search" data-assigned-id="#item.ProductId" />
</div>
My Partial View
<div class="group">
<button type="button" value="Button" data-toggle="collapse" data-target="#demo">
<span class="glyphicon glyphicon-plus"></span>
</button>
<div class="container">
<div class="row">
<div class=" col-sm-12">
#using (Html.BeginForm("Report", "Home", FormMethod.Get))
{
#Html.DisplayNameFor(m => m.Name)
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", style = "width: 155px", placeholder = Html.DisplayNameFor(n => n.Name})
#Html.HiddenFor(m => m.Id)
}
</div>
<div id="demo" class="collapse">
<div class="col-sm-12">
#Html.DisplayNameFor(model => model.StartDate)
#Html.TextBoxFor(m => m.StartDate, new { #class = "form-control", style = "width: 155px", placeholder = Html.DisplayNameFor(n => n.StartDate) })
#Html.DisplayNameFor(model => model.Distance)
#Html.DropDownListFor(m => m.Distance, Model.DistanceOptions, "All", new { #class = "form-control", style = "width: 150px;" })
</div>
</div>
</div>
</div>
</div>
Can anyone please guide me where I am going wrong?
I believe you need to add the event listeners to the button instead. This appears to work.
$('#demo').on('shown.bs.collapse', function () {
debugger;
$(this).parent().prev('button').find(".glyphicon-plus").removeClass("glyphicon-plus").addClass("glyphicon-minus");
}).on('hidden.bs.collapse', function () {
debugger;
console.log('hide');
$(this).parent().prev('button').find(".glyphicon-minus").removeClass("glyphicon-minus").addClass("glyphicon-plus");
});
And here is a link to fiddle that simply outputs 'show' or 'hide' to your console.log to show that it does indeed work.
https://jsfiddle.net/wuvrp0y3/
Edit for clarification:
You may need to change the selectors used within the functions, as the context of $(this) is no longer valid.
After comments;
It appears that you are calling the $(document).ready function only once, on page load (as you should be), and the -new- partial view does not have the events registered.
I would suggest creating a function that sets up those events (also turning off those events beforehand, as so;
function SetUpCollapse(){
$('.collapse').off('click shown.bs.collapse hidden.bs.collapse');
//This is necessary to prevent multiple calls from triggering this event multiple times.
$('.collapse').on('click', 'shown.bs.collapse', function () {
debugger;
$(this).parent().prev('button').find(".glyphicon-plus").removeClass("glyphicon-plus").addClass("glyphicon-minus");
}).on('hidden.bs.collapse', function () {
debugger;
console.log('hide');
$(this).parent().prev('button').find(".glyphicon-minus").removeClass("glyphicon-minus").addClass("glyphicon-plus");
});
}
Then, in your document.ready, call it;
$(document).ready(function(){
SetUpCollapse();
});
I assume you use ajax to load your partial view. However you do that, there should be an 'on completion' function, simply call that same function within that as well.
IE,
$.ajax({
url: "SomeURLHere",
type: "POST",
data: {data: data},
dataType: "html",
success: function (html) {
//append html
SetUpCollapse();
},
error: function (xhr, ajaxOptions, thrownError) {
}
});
Are your event listeners possibly missing an event?
from
$('.collapse').on('shown.bs.collapse', function () {
to
$('.collapse').on('click', '.shown.bs.collapse', function () {

How to Ajax POST after a Form Submit

I think this is pretty simple but I cannot find anywhere how to do this, as the title says, how do you do an ajax post after a successful submit form post. I tried to search for it but all I see is the reverse of what I need which is submit after an ajax post. I'll try to make a draft of a program very similar to what Im working on.
This is my form.
<h2>My Form </h2>
#using (Html.BeginForm(new { #class = "submitForm" }))
{
<label>Loan Amount</label>
#Html.DropDownListFor(model => model.Loan.LoanAmount, Model.DropDownOfLoanAmount, new { #class = "LoanAmount", #data_bind = "value: selectedLoanAmount" })
#Html.ValidationMessageFor(model => model.Loan.LoanAmount)
<label>Loan Receivable</label>
#Html.TextBoxFor(model => model.Loan.LoanReceivable, "{0:0,0.00}", new { #class = "LoanReceivable", #readonly = true, dir = "rtl", #data_bind = "value: loanReceivable" })
#Html.ValidationMessageFor(model => model.Loan.LoanReceivable)
<label>Interest</label>
#Html.TextBoxFor(model => model.Loan.Interest, "{0:0,0.00}", new { #readonly = true, #class = "Interest", dir = "rtl", #data_bind = "value: interest" })
<table class="input-group">
<tbody data-bind="foreach: loanDeductions">
<tr>
<td><strong data-bind='text: deductionName'></strong></td>
<td>
<input class="deductionCode form-control" data-bind='value: amount, valueUpdate: "afterkeydown"' /></td>
<td><a href='#' data-bind='click: $parent.removeLine'>Delete</a></td>
</tr>
</tbody>
</table>
<button type="button" class="btn btn-danger">Save Deduction</button>
<button type="submit" class="btn btn-primary">Save changes</button>
}
This is an example ajax post (dont mind the logic of the post):
$.ajax({
'url' :'#Url.Action("UpdateDeductionValues","LoanApp")',
'data': {amount : $('.LoanAmount').val()},
'success': function(result) {
$.each(result, function (idx, items) {
$('.' + items.Code + '').val(items.Amount.toFixed(2));
});
}});
Now what I want to happen is when I submit that form, if the submit is successful, the ajax post is triggered. So its like posting 2 times in one button, the difference is that the other one is a form submit while the other is an ajax post. PLS help.
What you should do is "take over the submit button" with your jQuery, and then use an ajax call inside.
For example having this submit button:
<input type="submit" value="Submit" onsubmit="$('#your-form-id-here').submit()">
And having this jQuery submit function with an ajax call, should give you a pretty good idea on what to do.
$('#your-form-id-here').submit(function (e) {
e.preventDefault();
var senddata = $(this).serializeArray();
var sendto = $(this).attr("action");
$.ajax({
url: sendto,
type: 'POST',
data: senddata,
success: function (data) {
$('.messages').html(data);
},
error: function (error) {
$('.messages').html(error);
}
});
});
This basically takes your normal form, and send it through your ajax call, to your normal form action, so basically it works just like normal, but you now have the opportunity to do stuff in your form action php file, and also in your ajax success data. For example you could use this to deliver validation messages directly to your user, without refreshing your site. And so on...
i'm not sure what you are trying to do, what the point of doing ajax request after submitting the form the page will reload anyway.
however if need need do the ajax request after the submitting the form you just need an ajax call. but that that will work on every time when page load.
what i think you need to do make two ajax request the first one is for the submitting the form and if the call is successful then call the second request.

Prevent from ajax call in MVC

Hi i am making my project in the asp.net,
basic expected behaviour -- fill form name , select master module(dropdown), select sub modules(dropdown), ajax passes id of submodule dropdown, create(submit).. it will submit all values,
now code is behaves---- fill form name, select master and submodule, while selecting submodule from second dropdown is calling the ajax call, and create action is called, so the form name and masterID(that is extracted from first dropdown) gone blank... so i need to prevent the ajax call to call the controller
Myform in razor view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Form</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FormName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FormName)
#Html.ValidationMessageFor(model => model.FormName)
</div>
<select id="State" name="state"></select><br />
<p>
<input id="sbmt" type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
My ajax call
$('#State').change(function () {
var a = $('#State').val();
var token = $('[name=__RequestVerificationToken]').val();
$.ajax({
url: "/form/create",
type: "POST",
data: { __RequestVerificationToken: token, 'SubID': a }
});
});
My controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Form form, int SubID)
{
if (ModelState.IsValid)
{
form.CreatedBy = 1;
form.SubId = SubID;
form.CreatedDate = DateTime.Now;
form.ModifyBy = 1;
form.ModifyDate = DateTime.Now;
form.IsActive = true;
form.IsDeleted = false;
db.Forms.Add(form);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.MasterID = new SelectList(db.Departments, "MasterId", "ModuleName", form.MasterID);
return View(form);
}
From the comments, you want to be able to post back the value of the selected state when you submit the form. The best approach would be to use a view model that includes the property SubId and bind your dropdownlist to that property (the SubId parameter in you POST method is then not necessary.
#Html.DropDownListFor(m => m.SubId, ....)
The alternative is to rename the control to SubId so it matches the parameter in your POST method
<select name="SubId" ...>
and delete the unnecessary javascript function $('#State').change(function () {...
I guess the easiest way for you would be to use MVC's ajax helpers. Change your form like so:
#using (Ajax.BeginForm("Create", "Home", null, new AjaxOptions { OnSuccess = "OnSuccess" }))
{
...
And afterwards add a javascript handler for onsuccess
function OnSuccess(){
alert("success");
}
This is barely functional code just to get you started.
PS. Make sure you add a reference to ~/Scripts/jquery.unobtrusive-ajax.min.js

Submit a form with anchor (<a>) tag with some value in ASP.Net MVC using Html.BeginFrom

I am using Html.BeginFrom ... to create a from Tag and Submit request to use external login providers.
The HttpPost action in Account Controller
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
I need to send the RetunUrl and the Provider to the above action method
Currently i am creating Multiple forms using a Foreach with Razor
#foreach (ExternalLoginViewModel loginViewModel in Model)
{
using (Html.BeginForm("ExternalLogin", "Account", new { Provider = loginViewModel.AuthenticationClientData.DisplayName, ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
#Html.AntiForgeryToken()
<a class="#loginViewModel.AnchorCssClass" style="#loginViewModel.AnchorCssStyle" href="#">
<div class="#loginViewModel.DivCssClass" style="#loginViewModel.DivCssStyle">
<span aria-hidden="true" class="#loginViewModel.IconCssClass"></span>
</div>
</a>
}
}
But i think it can be done using a single from but i dont know how i can provide the Provider value which varies with the anchorTag Something like :
using (Html.BeginForm("ExternalLogin", "Account", new { Provider = "<SomeValue>", ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
#Html.AntiForgeryToken()
#foreach (ExternalLoginViewModel loginViewModel in Model)
{
<a class="#loginViewModel.AnchorCssClass" style="#loginViewModel.AnchorCssStyle" href="#">
<div class="#loginViewModel.DivCssClass" style="#loginViewModel.DivCssStyle">
<span aria-hidden="true" class="#loginViewModel.IconCssClass"></span>
</div>
</a>
}
}
Javascript used in the earlier case is (it works fine)
<script type="text/javascript">
$(document).ready(function() {
$(document).on("click", ".CSSclassonAnchor", function (e) {
e.preventDefault();
var form = $(this).closest("form");
form.submit();
});
});
</script>
I think its somehow will be posssible to post data using an anchor Tag
Any help in this regard will be great.. Thanks
one way of doing it is adding a hidden field to the form, and populate it from javascript. In your view modify the BeginForm to no include Provider parameter and add a <input type="hidden" /> in the form:
using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.Hidden("Provider", "", new {id=hdnprovider})
#foreach (ExternalLoginViewModel loginViewModel in Model)
{
<a class="#loginViewModel.AnchorCssClass" style="#loginViewModel.AnchorCssStyle" href="#" data-name="#loginViewModel.AuthenticationClientData.DisplayName">
<div class="#loginViewModel.DivCssClass" style="#loginViewModel.DivCssStyle">
<span aria-hidden="true" class="#loginViewModel.IconCssClass"></span>
</div>
</a>
}
}
Then in Javascript use the data-name attribute of the link clicked and assign it to the hidden:
$(document).ready(function() {
$('a[data-name]').click(function (e) {
e.preventDefault();
var form = $(this).closest("form");
$("#hdnprovider").val($(this).data("Name"));
form.submit();
});
});
As the hidden has the name "Provider" it will be automatically binded to "Provider" parameter in your controller.

Categories

Resources