As per subject. The view looks like this.
#using System.Globalization
#model IEnumerable<TaskEngine.WebUI.Models.TaskViewModel>
<script src="../../Scripts/progress-task.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
url: '#Url.Action("Index", "Home")',
data: { from: "10/01/2014", to: "10/14/2014" },
dataType: "html",
success: function () {
alert('Success');
},
error: function (request) {
alert(request.responseText);
}
});
});
</script>
<div class="container">
<div class="row">
<div class="span16">
<div id="sitename">
xxxxxxxx
<span class="name">Workbasket</span>
</div>
<div class="row">
<div class="span16">
<table class="table table-striped table-condensed" id="task-table">
<thead>
<tr>
<th class="left">Client</th>
<th class="left">Task</th>
<th class="left">State</th>
<th class="left">Assigned By</th>
<th class="left">Assigned To</th>
<th class="left">Date Opened</th>
<th class="left">Date Due</th>
#* <th class="left">Date Closed</th>*#
<th class="left">Outcomes</th>
</tr>
</thead>
<tbody>
#foreach (var task in Model)
{
<tr>
<td><span>#task.ClientId</span></td>
<td><span class="nowrap">#task.TaskDescription</span></td>
<td><span class="nowrap">#task.CurrentState</span></td>
<td><span >#task.AssignedBy.Replace("CORPORATE\\", "").Replace(#".", " ")</span></td>
<td><span>#task.AssignedTo.Replace("CORPORATE\\", "").Replace(#".", " ")</span></td>
<td><span>#task.DateOpened.ToString("dd/MM/yyyy HH:mm")</span></td>
<td><span>#task.DateDue.ToString("dd/MM/yyyy HH:mm")</span></td>
#* <td><span>#(task.DateClosed.HasValue ? task.DateClosed.Value.ToShortDateString() : " - ")</span></td>*#
<td>
<span class="nowrap">
#Html.DropDownList(
"Outcomes",
new SelectList(task.Outcomes, "Id", "Name"), "---Please Select ---",
new Dictionary<string, object>
{
{"data-case-id", #task.CaseId }, {"data-task-log-id", #task.TaskLogId}, {"data-client-id", #task.ClientId}
})
</span>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="modal hide span8" id="complete-task-modal" tabindex="-1" role="dialog" aria-labelledby="complete-task-header" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="complete-task-header">Complete Task</h3>
</div>
<div class="modal-body">
<div class="row">
<div class="span8">
<div class="alert alert-info">
<label id="CurrentState"></label>
<label id="NewState"></label>
<label>Generated Tasks</label>
<ul id="task-list">
</ul>
</div>
</div>
</div>
<form id="form">
<input type="hidden" id="task-log-id" name="taskLogId" />
<input type="hidden" id="case-id" name="caseId" />
<input type="hidden" id="outcome-id" name="triggerId" />
<input type="hidden" id="client-id" name="clientId" />
<div id="popup">
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn" id="close" data-dismiss="modal" aria-hidden="true">Go Back</button>
<button class="btn btn-primary" id="confirm-task">Confirm</button>
</div>
</div>
</div>
This is the controller method.
public ActionResult Index(DateTime? from, DateTime? to)
{
var usergroups = GetGroups(HttpContext.User.Identity.Name);
var model = _taskLogger.GetTasks(from, to)
.Select(task => new TaskViewModel
{
TaskLogId = task.TaskLogId,
CaseId = task.CaseId,
ClientId = task.ClientId,
TaskDescription = task.Description,
AssignedBy = task.AssignedBy,
AssignedTo = task.AssignedTo.Trim(),
DateOpened = task.DateCreated,
DateClosed = task.DateClosed,
DateDue = task.DateDue
}).ToList()
.Where(x => IsAvailableToUser(x.AssignedTo, usergroups))
.OrderBy(x => x.DateDue);
foreach (var task in model)
{
var workflow = _workflowEngine.GetCase(task.CaseId);
task.CurrentState = workflow.State.ToNonPascalString();
task.Outcomes = workflow.GetPermittedTriggers().OrderBy(x => x.Name).ToList();
}
ModelState.Clear();
return View(model);
}
When the model is returned following the ajax post, the dataset is different, as expected, however, within the datatable in the view it still displays the old data.
Having done some googling on this issue, I've tried clearing the modelstate but that makes no difference and from what I've read, it only seems to affect HTMLHelpers anyway.
I'm not sure if this is an issue with the datatable or just a refresh issue with the view itself. Any input would be appreciated.
Ajax calls stays on the same page. If you want to update the page with the view returned by public ActionResult Index(DateTime? from, DateTime? to) then you need to add it to the DOM in the success callback
$.ajax({
url: '#Url.Action("Index", "Home")',
data: { from: "10/01/2014", to: "10/14/2014" },
dataType: "html",
success: function (data) {
$('#someElement').html(data); // add the returned html to the DOM
},
....
});
but looking at the code in the controller it appears to be the same view as the original view so perhaps you really want to redirect rather than stay on the same page
Related
I want to add new item by send form Ajax to controller and then return json response
this is form to submit putting in partial view "_AddSubAccount"
#model EndSubAccountVM
#using Microsoft.AspNetCore.Mvc.Localization
#inject IViewLocalizer localizer
<form method="post" onsubmit="sendAjax();">
<!-- Modal -->
<div class="modal fade rounded-lg shadow" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content ">
<div class="modal-header bg-info text-white d-flex">
<h5 class="modal-title font-weight-bold" id="exampleModalLabel"><i class="fas fa-plus-circle"></i> #localizer["AddSubAccount"]</h5>
<button type="button" class="close align-self-start mx-1" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body container shadow">
<div class="form-inline mt-3">
<label class="font-weight-bold text-muted align-self-start mx-1 mb-2">#localizer["AccountNameAR"]</label>
<input type="text" asp-for="Name" id="nameAr"
class="form-control w-100 shadow" />
<span class="text-danger" asp-validation-for="Name"></span>
</div>
<div class="form-inline my-3">
<label class="font-weight-bold text-muted align-self-start mx-1 mb-2">#localizer["AccountNameEN"]</label>
<input type="text" asp-for="NameEN" class="form-control w-100 shadow" id="nameEn" />
<span class="text-danger" asp-validation-for="NameEN"></span>
</div>
<input type="hidden" asp-for="AccountTreeId" value="#ViewBag.mainAccountID" id="mainAcc" />
</div>
<div class="modal-footer d-flex justify-content-end">
<button type="button" class="shadow btn btn-secondary mx-1" data-dismiss="modal"><i class="fas fa-cancel"></i> #localizer["Cancel"]</button>
<button type="submit" class="shadow btn btn-primary mx-1"><i class="fas fa-save"></i> #localizer["Save"]</button>
</div>
</div>
</div>
</div>
</form>
and this is View which i inject partial view in call "Add"
#model IEnumerable<EndSubAccount>
#using Microsoft.AspNetCore.Mvc.Localization
#using System.Globalization
#using NToastNotify;
#inject IViewLocalizer localizer
#inject IToastNotification toaster
<h3 class="jumbotron p-3 mb-0 bg-primary-cus text-center text-white font-weight-bold border-cus-3 w-75 container">
<i class="fas fa-list-alt"></i> #localizer["subAccountFor"]
#(CultureInfo.CurrentCulture.Name.StartsWith("ar") ? ViewBag.mainAccountAR : ViewBag.mainAccountEN)
</h3>
<div class="w-75 container p-0 my-2">
<!-- Button trigger modal -->
<button type="button" class="btn btn-sm btn-primary btn-primary-cus addSubAccount" data-toggle="modal" data-target="#exampleModal">
<i class="fas fa-plus-circle"></i> #localizer["addSubAccount"]
</button>
</div>
<table class="table table-sm table-striped table-hover container w-75 rounded-lg">
<thead class="text-white font-weight-bold bg-primary-cus">
<tr>
<th>#localizer["AccountName"]</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
#if (CultureInfo.CurrentCulture.Name.StartsWith("ar"))
{
<td>#item.Name</td>
}
else
{
<td>#item.NameEN</td>
}
<td class="d-flex justify-content-end">
<a asp-rout-id="#item.Id" asp-action="Edit" class="btn btn-sm btn-outline-info mx-1"><i class="fas fa-pencil-alt"></i> #localizer["Edit"]</a>
<a asp-route-id="#item.Id" id="del-btn" class="btn btn-sm btn-danger mx-1"><i class="fas fa-trash-alt"></i> #localizer["Delete"]</a>
</td>
</tr>
}
</tbody>
</table>
<partial name="_AddSubAccount" model="new EndSubAccountVM()" />
<!--! Template To add row in Table -->
<div class="d-none" id="template">
<tr>
#if (CultureInfo.CurrentCulture.Name.StartsWith("ar"))
{
<td>{nameAr}</td>
}
else
{
<td>{nameEn}</td>
}
<td class="d-flex justify-content-end">
<a asp-rout-id="{id}" asp-action="Edit" class="btn btn-sm btn-outline-info mx-1"><i class="fas fa-pencil-alt"></i> #localizer["Edit"]</a>
<a asp-route-id="{id}" id="del-btn" class="btn btn-sm btn-danger mx-1"><i class="fas fa-trash-alt"></i> #localizer["Delete"]</a>
</td>
</tr>
</div>
#section Scripts{
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
function sendAjax() {
let form = $('form').serialize();
var row2Append = $('table tbody tr:last');
var nameAr = $('#nameAr').val();
var nameEn = $('#nameEn').val();
$.ajax({
url: #Url.Action("Add", "EndSubAccount"),
type: 'post',
data: form,
dataType: 'json',
success: function (response) {
var accountName = CultureInfo.CurrentCulture.Name.StartsWith("ar") ? response.Name : response.NameEN;
var data2Add = $('#template').html().replace('{nameAr}', response.Name)
.replace('{nameEn}', response.NameEN)
.replace('{id}', response.Id);
row2Append.append(data2Add).fadeIn();
toaster.success(localizer["accountSaved", ViewBag.AccountName]);
},
error: function () {
alert({#localizer["someThingError"]});
}
//end of Ajax
});
}
</script>
}
and this is post action to save item and retrun json
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Add(EndSubAccountVM accountVM)
{
var nameArExist = await _context.AccountsTrees.FirstOrDefaultAsync(x => x.Name == accountVM.Name);
var nameEnExist = await _context.AccountsTrees.FirstOrDefaultAsync(x => x.NameEN == accountVM.NameEN);
var AccountIdExist = await _context.AccountsTrees.FirstOrDefaultAsync(x => x.Id == accountVM.AccountTreeId);
// validate Data
if (nameArExist != null)
{
ModelState.AddModelError("Name", _localizer["nameExist"]);
}
if (nameEnExist != null)
{
ModelState.AddModelError("NameEN", _localizer["nameExist"]);
}
if (AccountIdExist == null)
{
ModelState.AddModelError("AccountId", _localizer["AccountIdExist"]);
}
var accountName = CultureInfo.CurrentCulture.Name.StartsWith("ar")? accountVM.Name : accountVM.NameEN;
if (!ModelState.IsValid)
{
_notify.AddErrorToastMessage(_localizer["accountNotSave", accountName]);
return new JsonResult(accountVM);
}
var account2Add = new EndSubAccount()
{
Name = accountVM.Name,
NameEN = accountVM.NameEN,
_lastUpdate = DateTime.Now,
_UserId = Convert.ToInt32(User.FindFirst("UserId").Value),
AccountTreeId = accountVM.AccountTreeId
};
var accountSaved = CultureInfo.CurrentCulture.Name.StartsWith("ar") ? account2Add.Name : account2Add.NameEN;
ViewBag.AccountName = accountName;
await _context.EndSubAccounts.AddAsync(account2Add);
await _context.SaveChangesAsync();
return new JsonResult(accountSaved);
}
when i click on submit it go to action directly without call AJAX so action return response as json in view page not return to AJAX code
so why AJAX Not Work ?
Firstly,try to remove onsubmit="sendAjax();" and change your button to:
<button type="button" class="shadow btn btn-primary mx-1" onclick="sendAjax()"><i class="fas fa-save"></i> #localizer["Save"]</button>
Then the ajax will be called.Since you use [ValidateAntiForgeryToken] in your action,you need to add Antiforgery token to your ajax like this:
function sendAjax() {
let form = $('form').serialize();
var row2Append = $('table tbody tr:last');
var nameAr = $('#nameAr').val();
var nameEn = $('#nameEn').val();
$.ajax({
url: #Url.Action("Add", "EndSubAccount"),
type: 'post',
data: form,
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
dataType: 'json',
success: function (response) {
var accountName = CultureInfo.CurrentCulture.Name.StartsWith("ar") ? response.Name : response.NameEN;
var data2Add = $('#template').html().replace('{nameAr}', response.Name)
.replace('{nameEn}', response.NameEN)
.replace('{id}', response.Id);
row2Append.append(data2Add).fadeIn();
toaster.success(localizer["accountSaved", ViewBag.AccountName]);
},
error: function () {
alert({#localizer["someThingError"]});
}
//end of Ajax
});
----------
}
your form is posting back to server before onsubmit="sendAjax();" fires
so try this :
$("form").submit(function(e){
return false;
});
or :
$('form').on('submit', function(e){
e.preventDefault();
});
further you can remove
onsubmit="sendAjax();"
from form
and change
type="submit"
to
type="button"
for save button
and add
onclick="sendAjax();"
to save button
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I have a requirement where I need to display a Modal popup. When the user clicks on the link inside a grid, then that has to open a modal popup with the respective values.This is the partial view code.I am using in this i have placed the edit button after clicking on it it should show PopUp to edit the details and should save it to the database. can some one help me with this?
#model IEnumerable<LMS.ViewModels.TemporaryStaff.VMTemporaryStaffResponse>
<div class="card mt-4 mb-5 ml-3 mr-3">
<div class="card-body">
<p class="card-title">View TemporaryStaff</p>
<div class="row">
<div class="col-12">
<div class="table-responsive">
<table id="order-listing" class="table">
<thead>
<tr>
<th class="label">Stafftemp ID</th>
<th class="label">StaffName</th>
<th class="label">Created On</th>
<th class="label">Status</th>
<th class="label">Edit</th>
<th class="label">View QR Code</th>
</tr>
</thead>
<tbody class="table-body">
#foreach (var item in Model)
{
<tr class="table-row">
<td>
#Html.DisplayFor(modelItem => item.StafftempID)
</td>
<td>
#Html.DisplayFor(modelItem => item.StaffName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Createdon)
</td>
<td>
#if (item.Status)
{
<label class='badge badge-success'>Active</label>
}
else
{
<label class='badge badge-danger'>In-Active</label>
}
</td>
<td>
<a href="#Url.Action("GetTemporaryStaffById", "TemporaryStaff", item)">
<i class="fa fa-edit"></i>
</a>
#*<a onclick="showInPopup('#Url.Action("GetTemporaryStaffById", "TemporaryStaff", item)'"
class="btn btn-info text-white"><i class="fa fa-edit"></i></a>*#
</td>
<td>
<button type="submit" class="btn btn-success mr-2">QR Code</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
function OpenModal(recordId) {
$.ajax({
type: "GET",
url: "/TemporaryStaff/GetTemporaryStaffById",
datatype: "Json",
data: { id: recordId },
success: function (data) {
$('body').append($('<div id="divPopup"></div>'));
$("#divPopup").html(data);
$('#popupScreen').modal('show');
event.preventDefault();
return false;
},
error: function (error) {
event.preventDefault();
return false;
}
});
};
With this AJAX call, you can make a popup page with the values of object, you can send id as parameter, after that in controller, you can return a partial view, but you will design the partial view with name and id popupScreen. In controller you will have to use a parameter which name is id. Modal page looks like something below
#model Project.Models.TemporaryStaffModel
#{
//Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Ajax.BeginForm("StaffSave", "TemporaryStaff", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "OperationSuccess", OnFailure = "OperationFail" }, new { id = "StaffForm", name = "StaffForm" }))
{
<div class="modal draggable fade" id="popupScreen" tabindex="-1" data-backdrop="static" data-keyboard="false" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-popin modal-l">
<div class="modal-content">
<div class="block block-bordered">
<div class="block-header bg-gray-lighter">
<ul class="block-options">
<li>
<button data-dismiss="modal" data-toggle="tooltip" data-placement="right" title="Close" class="closePopupButton" type="button"><i class="si si-close"></i></button>
</li>
</ul>
<h3 class="block-title">#ViewBag.Header</h3>
</div>
<div class="block-content">
<div class="form-horizontal">
<div class="form-group">
<label class="col-md-3 control-label">#Html.LabelFor(m => m.SaveDate)</label>
<div class="col-md-9">
#Html.DatePickerFor(m => m.SaveDate).HtmlAttributes(new { #Id = "dtpSaveDateIslem", style = "width:100%", required = "required", validationMessage = "Field Required" })
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-primary" type="button" id="btnSave" name="btnSave" value="Save" onclick="ValidationControl()">
<i class="fa fa-save"></i> Save
</button>
<button class="btn btn-sm btn-primary" type="submit" id="btnSave2" name="btnSave2" value="Save" style="display: none">
<i class="fa fa-save"></i> Save
</button>
</div>
</div>
</div>
</div>
</div>
}
What am I doing wrong?
I want to pass Id to the controller where I can use it.
My controller
[HttpGet]
public ActionResult ListCoach(int id)
{
List<Training> ListCoachTraining = _TraningService.ListCoach(id);
var ChoachList = _TraningService.Coach(id);
return View(ChoachList);
}
My view - what is correct way call the script? It doesn't work right now:
<div class="container">
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-4">
<div class="card" style="width: 18rem;">
<img src="~/Content/no_foto.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">#item.Name</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<div id="textButton">
Go to anywhere
<a id="btnSave" class="btn btn-primary">Go to anywhere</a>
<input class="btn btn-primary" type="button" id="btnSave" value="Save" />
</div>
</div>
</div>
</div>
}
</div>
</div>
//call the script
<script src="#Url.Content("~/scripts/ManagerAccount.js")" type="text/javascript"></script>
My script - I use Ajax for it. There I want to pass id to the controller:
function PassToContoller(data) {
$("#btnSave").click(function () {
$.ajax({
type: "Get",
url: '/TrainingType/ListCoach',
data: { id: data },
success: function (data) {
window.location.href = '/appUser/ManageAccount';
//return data;
},
error: function () {
$("#loader").fadeOut("slow");
console.log("error1");
}
});
});
};
You haven't call the function accordingly. You are expecting your PassToContoller function should invoke while you click on save in your case either you have to call this function with btnSave onlick or onClick="PassToContoller(#item.Name)"
I am showing you both here:
When onClick="PassToContoller(#item.Name)" In Line:
Razor HTML
<div class="container">
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-4">
<div class="card" style="width: 18rem;">
#*<img src="~/Content/no_foto.png" class="card-img-top" alt="...">*#
<div class="card-body">
<h5 class="card-title">#item.Name</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<div id="textButton">
Go to anywhere
<a id="btnSave" class="btn btn-primary">Go to anywhere</a>
<input class="btn btn-primary" type="button" id="btnSave" onClick="PassToContoller(#item.Name)" value="Save" />
</div>
</div>
</div>
</div>
}
</div>
</div>
Script:
<script>
function PassToContoller(data) {
alert(data);
$.ajax({
type: "GET",
url: '/ListCoachController/ListCoach',
data: { id: data },
success: function (data) {
console.log(data);
window.location.href = '/appUser/ManageAccount';
return data;
},
error: function () {
$("#loader").fadeOut("slow");
console.log("error1");
}
});
}
</script>
Output:
Aother way btnSave Onlick:
In this you need few modifications:
Need to introduce a input type text which will be hidden it will
contrain a value like this <input type="text" id="getValue" value="#item.Name" hidden /> and will pass that hidden value when you
would click the button.
Another thing is your btnSave seems you have used same for other button as well so your onclick function will getConfused which event to fired. So need to set unique btn id Now rest of the same like below:
Razor HTML
<div class="container">
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-4">
<div class="card" style="width: 18rem;">
#*<img src="~/Content/no_foto.png" class="card-img-top" alt="...">*#
<div class="card-body">
<h5 class="card-title">#item.Name</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<div id="textButton">
Go to anywhere
<a id="btnSave" class="btn btn-primary">Go to anywhere</a>
<input class="btn btn-primary" type="button" id="btnNewSave" value="Save" />
<input type="text" id="getValue" value="#item.Name" hidden />
</div>
</div>
</div>
</div>
}
</div>
</div>
Script:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script>
$(document).ready(function () {
$("#btnNewSave").click(function () {
var data = $("#getValue").val();
$.ajax({
type: "GET",
url: '/ListCoachController/AnotherListCoach',
data: { id: data },
success: function (data) {
console.log(data);
window.location.href = '/appUser/ManageAccount';
return data;
},
error: function () {
$("#loader").fadeOut("slow");
console.log("error1");
}
});
});
});
</script>
}
Update:
Based on your new requirement on comment you just need to update your HTML like below:
<div class="container">
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-4">
<div class="card" style="width: 18rem;">
#*<img src="~/Content/no_foto.png" class="card-img-top" alt="...">*#
<div class="card-body">
<h5 class="card-title">#item.Name</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<div id="textButton">
Go to anywhere
<a class="btn btn-primary" onClick="PassToContoller(#item.Name)">Go to anywhere</a>
<input class="btn btn-primary" type="button" onClick="PassToContoller(#item.Name)" value="Save" />
<input type="text" id="getValue" value="#item.Name" hidden />
</div>
</div>
</div>
</div>
}
</div>
</div>
Note: You have to get rid of id="btnSave" from all the <a> and <button> and need to replace with
onClick="PassToContoller(#item.Name)" it will pass all of your
value. No matter how many cycle you have.
Update with Comment Can I do without?:
HTML:
<div class="container">
<div class="row">
#foreach (var item in Model)
{
<div class="col-md-4">
<div class="card" style="width: 18rem;">
#*<img src="~/Content/no_foto.png" class="card-img-top" alt="...">*#
<div class="card-body">
<h5 class="card-title">#item.Name</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<div id="textButton">
<a href="#" class="btn btn-primary" >Go to anywhere</a>
<a class="btn btn-primary">Go to anywhere</a>
<input class="btn btn-primary" type="button" value="Save" />
<input type="text" id="getValue" value="#item.Name" hidden />
</div>
</div>
</div>
</div>
}
</div>
</div>
Script:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script>
function PassToContoller(data) {
alert(data);
$.ajax({
type: "GET",
url: '/UserLog/AnotherListCoach',
data: { id: data },
success: function (data) {
console.log(data);
window.location.href = '/appUser/ManageAccount';
return data;
},
error: function () {
$("#loader").fadeOut("slow");
console.log("error1");
}
});
}
$(document).ready(function () {
$("a").click(function () {
var data = $("#getValue").val();
var callFunc = PassToContoller(data)
});
$(":button").click(function () {
var data = $("#getValue").val();
var callFunc = PassToContoller(data)
});
});
</script>
}
Hope it would guide you accordingly. You can used either of the approach.
With GET method, you should pass the data via query string
/TrainingType/ListCoach?id=1
In ASP.NET MVC, we have default route template is {Controller}/{Action}/{id}
So, alternative we can use this URL
/TrainingType/ListCoach/1
Code searchView and PartialResultView
SearchView
#model Shared.Model.Search.GLSearch
#{
ViewData["Title"] = "Search GL";
}
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item">UBold</li>
<li class="breadcrumb-item">Forms</li>
<li class="breadcrumb-item active">Elements</li>
</ol>
</div>
<h4 class="page-title">Search Customer</h4>
</div>
</div>
</div>
<!-- end page title -->
<form asp-action="" asp-controller="" method="post">
<div class="row">
<div class="col-lg-12">
<div class="card-box">
<div class="form-row">
<div class="form-group col-md-2">
<label asp-for="Name" class="col-form-label"></label>
<input asp-for="Name" type="text" class="form-control" />
</div>
<div class="form-group col-md-2">
<label asp-for="Code" class="col-form-label"></label>
<input asp-for="Code" type="text" class="form-control" />
</div>
<div class="form-group col-md-3">
<label asp-for="GLSectionId" class="col-form-label">Section </label>
<select asp-for="GLSectionId" asp-items="#(new SelectList(Model.glSections,"Id","Name"))" class="form-control">
<option value="">Choose</option>
</select>
</div>
<div class="form-group col-md-3">
<label asp-for="GLGroupId" class="col-form-label">Group</label>
<select asp-for="GLGroupId" asp-items="#(new SelectList(Model.glGroups,"Id","Name"))" class="form-control">
<option value="">Choose</option>
</select>
</div>
<button type="button" id="search" class="btn btn-primary waves-effect waves-light">Search</button>
</div>
</div> <!-- end card-box -->
</div> <!-- end col -->
</div> <!-- end row -->
</form>
<div id="view-all"></div>
Search_PartiaView
#model PagedResult<Shared.Model.Masters.GLMaster.GLViewModel>
#{
}
#if (Model == null || Model.RowCount == 0)
{
<p>No results found</p>
}
else
{
<div class="col-lg-12">
<div class="card-box">
<h4 class="header-title">Customers</h4>
<p class="sub-header">
</p>
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th data-priority="1">#</th>
<th data-priority="3">Name</th>
<th data-priority="6">Code</th>
<th data-priority="6">Section</th>
<th data-priority="6">Group</th>
<th data-priority="6">
<a onclick="showInPopup('#Url.Action("AddOrEditGL","GLMaster",new {area = "Masters"},Context.Request.Scheme)','New GL')" class="btn btn-success text-white"><i class="fas fa-random"></i> New GL</a>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Results)
{
<tr>
<th scope="row">#item.Id</th>
<td>#item.Name</td>
<td>#item.Code</td>
<td>#item.GLSection</td>
<td>#item.GLGroup</td>
<td>
<div>
<a onclick="showInPopup('#Url.Action("AddOrEditGL","GLMaster",new { area= "Masters",id = item.Id},Context.Request.Scheme)','Update GL')" class="btn btn-info text-white"><i class="fas fa-pencil-alt"></i> Edit</a>
<form asp-area="Masters" asp-action="DeleteGL" asp-route-id="#item.Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<input type="submit" value="Delete" class="btn btn-danger" />
</form>
</div>
</td>
</tr>
}
</tbody>
</table>
</div> <!-- end table-responsive-->
</div> <!-- end card-box -->
</div> <!-- end col -->
<!-- Responsive Table js -->
}
Partial View (AddEditGL)
#model Shared.Model.Masters.GLMaster.GLModel
#{
Layout = null;
ViewData["Title"] = "Add Customer";
}
<div class="row">
<div class="col-lg-12">
<div class="card-box">
<form asp-action="AddOrEditGL" asp-controller="GLMaster" asp-area="Masters" asp-route-id="#Model.Id" onsubmit="return jQueryAjaxPost(this);">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="#Model.Id" />
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" type="text" class="form-control">
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label asp-for="NameLang" class="control-label"></label>
<input asp-for="NameLang" type="text" class="form-control">
<span asp-validation-for="NameLang" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-6 offset-md-3">
<input type="submit" value="Submit" class="btn btn-primary btn-block" />
</div>
</div>
</form>
</div> <!-- end card-box -->
</div> <!-- end col -->
</div> <!-- end row -->
I have View with Partial view (is for results in table) . When i click Edit button in Search_PartiaView
i need to open popup (Partial View (AddEditGL))
and data should be loaded ajax and submit the button after update.. I need to use jquery unobtrusive validation in popup and also without refresh the page ..Please let me know hw to do..Thanks
EDIT
I Have implemented similar to this Ajax crud popup
I Have Main view and Partial view. Also AddOrEdit View for Add/edit Master.
My Current solution works.. But inmy main view i have filter based on 2 filds.
After add/edit grid load all the result but if filter applied i also need to filter the grid ..
My Javascript code Here:
jQueryAjaxPost = form => {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
if (res.isValid) {
$('#view-all').html(res.html) --- here actually data coming all without filter
$('#form-modal .modal-body.p-4').html('');
$('#form-modal .modal-title').html('');
$('#form-modal').modal('hide');
showAll(4, 1); --- it is the javascript fuction call to call the
api again
}
else
$('#form-modal .modal-body.p-4').html(res.html);
},
error: function (err) {
console.log(err)
}
})
//to prevent default form submit event
return false;
} catch (ex) {
console.log(ex)
}
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEditGL(int id,GLModel glModel)
{
if (ModelState.IsValid)
{
var mappedGL = _mapper.Map<GLDTO>(glModel);
//Insert
if (id == 0)
{
await _glService.CreateGL(mappedGL);
}
//Update
else
{
await _glService.UpdateGL(mappedGL);
//Call Update
}
// How do i filter the based on Main view form controls
return Json(new { isValid = true, html = Helper.RenderRazorViewToString(this, "_GLViewAll", null) });
}
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEditGL", glModel) });
}
my Current solution call the api again ( 2 server calls) one for update and another for call update table .. i need to do the same in single call ..Please help to do?
Note: I dont need complete solution , I only need to how to get the AddOrEditGL Controller post method Main view form control text fieds text to filter in DB
If you want to update/add and show the searched data in one request,The quick way is to copy the SearchGLPartial code to the AddOrEditGL function and pass the pageSize,pageIndex,name,code,GLSectionId and GlGroupId by ajax:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEditGL(int id,GLModel glModel,string name,string code,string GLSectionId,string GlGroupId...)
{
if (ModelState.IsValid)
{
var mappedGL = _mapper.Map<GLDTO>(glModel);
//Insert or
//Update
//copy the SearchGLPartial code here and return view with data
}
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEditGL", glModel) });
}
If you just do not want to remove showViewAll() jquery,I think you could set session for the filter condition when you first search the data in SearchGLPartial action.Then in your AddOrEdit action,get the session and set the correct url.Finally,you could get the url in ajax success response:
public IActionResult SearchGLPartial(string name,string code,string GLSectionId,string GLGroupId)
{
HttpContext.Session.SetString("name", name);
HttpContext.Session.SetString("code", code);
HttpContext.Session.SetString("GLSectionId", GLSectionId);
HttpContext.Session.SetString("GLGroupId", GLGroupId);
var data = Gllist.Where(a => a.Name.Contains(name) & a.Code.Contains(code)).FirstOrDefault();//filter by yourself
return PartialView("_Search", data);
}
AddOrEdit:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEditGL(int id,GLModel glModel)
{
if (ModelState.IsValid)
{
//Insert
//Update
var name = HttpContext.Session.GetString("name");
//other session data...
return Json(new { isValid = true, url="Home/Index?name="+name+"&code="+xxx+"&...."});
}
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEditGL", glModel) });
}
Then your ajax:
success: function (res) {
if (res.isValid) {
window.location.href = response.url;
}
else
$('#form-modal .modal-body.p-4').html(res.html);
},
I recommend using the jQuery Unobtrusive AJAX library. Its very easy to use:
It can fetch partial views and place them in a container of your choice using the
data-ajax-update="#panel"
Click here
<div id="panel"></div>
This is an example of a controller action that would return the modal:
public IActionResult GetEditModal() => Partial("ViewName");
Then when the modal is placed in your container, using the data-ajax-success attribute a callback method is called, parse the form using the jQuery Unobtrusive Validation like this:
function SuccessCallback() {
//You can also use the keyword "this" instead of getting the form with jquery
$.validator.unobtrusive.parse($(this));
//or
$.validator.unobtrusive.parse($form);
}
Very useful resources : Link - jQuery Unobtrusive AJAX - GitHub
Update
What i did in previous projects is to include an empty edit modal (a modal with an empty body) then using the library and the data-ajax-update i would replace the body of that modal every time the user pressed the edit button on a table item like this:
<div class="modal fade" id="eModal" data-keyboard="false" data-backdrop="static">
<div class="modal-dialog modal-lg">
<div class="modal-content id="modalContentE">
<div class="modal-header">
<h4 class="modal-title"><i class="nav-icon fas fa-edit"></i> Edit Data</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="fas fa-times-circle text-white"></i></span>
</button>
</div>
//New data goes here
</div>
</div>
</div>
And your add Modal would be a regular full modal and each time the user use it to submit data, clear the form.
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.