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
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
I would like whichever button been clicked I want to call the same function.
for now I have six card on View but work only one first. Other dosent work
My view
<h2>Our workouts</h2>
<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/not-found-image.jpg" 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="btnNewSave" class="btn btn-primary">Go to anywhere</a>
<input type="text" id="getValue" value="#item.Id" hidden />
</div>
</div>
</div>
</div>
}
</div>
</div>
My controller:
[HttpGet]
public ActionResult ListCoach(int? Id)
{
var ChoachList = _TraningService.Coach(Id);
return View(ChoachList);
}
script
I call My script from View use helper section
#section scripts {
<script>
$(document).ready(function () {
$("#btnNewSave").click(function () {
var data = $("#getValue").val();
$.ajax({
type: "GET",
url: '/TrainingType/ListCoach',
data: { id: data },
success: function (data) {
console.log(data);
window.location.href = '/TrainingType/ListCoach';
return data;
},
error: function () {
$("#loader").fadeOut("slow");
console.log("error1");
}
});
});
});
</script>
}
You should try this way, because your type of buttons are diffrent as per current scenario <a> and button so below way you could try.
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[name=link]").on("click", function () {
var valueOfClickedTag = $(this).data("index");
alert("Clicked On Anchor: " + valueOfClickedTag);
var callFunc = PassToContoller(valueOfClickedTag)
});
$(":button[id=GoToAnywhere3]").on("click", function () {
var valueOfClickedBtn = $(this).data("index");
var callFunc = PassToContoller(valueOfClickedBtn )
});
});
</script>
}
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.StudentID</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" data-index="#item.Name" name="link">Go to anywhere</a>
<input class="btn btn-primary" type="button" id="GoToAnywhere3" data-index="#item.StudentID" value="Save" />
<input type="text" class="inputVal" id="getValue" value="#item.Name" hidden />
</div>
</div>
</div>
</div>
}
</div>
</div>
Output:
Note: <input type="text" class="inputVal" id="getValue" value="#item.StudentID" hidden /> is not needed anymore.
Hope it would completely resolve your problem.
Firstly make use of button type rather than an a. With that change, you can use the onclick event in two ways:
First opt:
<button class="btn btn-primary list-coaches" onclick="listCoaches()">List Coaches</button>
function listCoaches() { ... }
Second opt:
<button class="btn btn-primary list-coaches">List Coaches</button>
$('.list-coaches').click(function() { ... });
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 a page in ASP.NET Core 3.0 with RAZOR(no MVC), with a partial page loaded with AJAX; load works well but validation rules no. Validation with "required" notation on otherinput fields also works well.
This is my main page:
<a class="nav-link showposition text-dark text-center p-0 collapsed" id="ShowPosition" href='ShowPosition'>#item.Sale_Order_Position</a>
<div class="card shadow mb-4 collapse" aria-labelledby="ShowPosition">
<div id="DetailContents">
</div>
</div>
<script>
jQuery(function($) {
$('.showposition').on('click', function (e) {
e.preventDefault();
$.ajax({
url: $(this).attr('href'),
type: 'GET',
cache: false,
headers: {
RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
}
}).done(function(result) {
$('#DetailContents').html(result);
//Setup Position details
$('#SavePositionForm').SetupPositionDetails();
});
});
(function( $ ){
$.fn.SetupPositionDetails = function () {
$("#SavePositionForm").removeData("validator");
$("#SavePositionForm").removeData("unobtrusiveValidator");
$.validator.unobtrusive.parse("#SavePositionForm");
$("#SavePositionForm").validate({
debug: true,
rules: {
inp_NetPrice: {
required: true
}
}
});
};
})(jQuery);
});
</script>
And this is my Partial View:
<form id="SavePositionForm" class="needs-validation" novalidate>
<div class="col-sm-12 col-md-12 col-lg-6 col-xl-6">
<div class="row">
<div class="col div_image pl-0">
<label class="bg-white"><i class="fr fa-newspaper mr-2"></i><localize>Net price</localize></label>
</div>
<div class="col-sm-6 col-md-6">
<input class="form-control form-control-sm" type="number" step="any" name="inp_NetPrice" id="inp_NetPrice" asp-for="#Model.Item1.Net_Price" value="#Model.Item1.Net_Price"/>
</div>
</div>
</div>
</form>
The problem is "inp_NetPrice" validation not working.
I have also try this script, in main partial page(i know, it's not a good idea to put script in partial pages but I would like to try) without success:
$(document).ready(function () {
$("#SavePositionForm").validate({
debug: true,
rules: {
inp_NetPrice: {
required: true
}
}
});
$("#SavePositionForm").removeData("validator");
$("#SavePositionForm").removeData("unobtrusiveValidator");
$.validator.unobtrusive.parse("#SavePositionForm");
});
Any suggestions?
Thanks.
EDIT:
Generated HTML:
<div class="col-sm-12 col-md-12 col-lg-6 col-xl-6">
<div class="row">
<div class="col div_image pl-0">
<label class="bg-white"><i class="fa fa-newspaper mr-2"></i>Net price</label>
</div>
<div class="col-sm-6 col-md-6">
<input class="form-control form-control-sm" id="inp_NetPrice" name="inp_NetPrice" value="" type="number" step="any">
</div>
</div>
</div>
Problem fixed removing
name="inp_NetPrice"
because i have
name="inp_NetPrice" id="inp_NetPrice" asp-for="#Model.Item1.Net_Price"
my index page is here
<div ng-app="CommentApp" ng-controller="MyController">
<div class=" col-md-12">
<div class="alert alert-info"><h2 class="text-center">Comment App</h2></div>
<div id="CommentList" class="container col-md-7" scroll="Comments" style="height:650px; overflow:scroll">
<div class="row" style="border:0px solid;padding:20px;" ng-repeat="Comment in Comments | orderBy:'LastUpdateTime'">
<div class="well well-sm row">
<div class="col-md-8">
**<h3><text style="color:mediumpurple;" e-form="rowform" data-ng-model="UpdateCommentText" editable-text="Comment.CommentText">{{Comment.CommentText || 'Empty'}}</text></h3>**
</div>
<div class="col-md-4 pull-right" style="margin-top:17px">
<div class="buttons pull-right">
<form editable-form name="rowform" ng-show="rowform.$visible" class="form-buttons form-inline">
<button type="submit" ng-disabled="rowform.$waiting" ng-click="EditComment()" class="btn btn-primary">
Save
</button>
<button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" class="btn btn-default">
Cancel
</button>
</form>
</div>
<div class="buttons pull-right" ng-show="!rowform.$visible">
<button class="btn btn-primary" ng-click="rowform.$show()">Edit</button>
<button class="btn btn-danger" ng-click="RemoveComment(Comment)">Delete</button>
</div>
</div>
</div>
<div class="col-md-12 row" style="margin-bottom:10px" ng-repeat="img in Comment.Images">
<img style="margin-bottom:15px" src="{{img}}" />
</div>
<h2 class="pull-right" style="color:green;font-size:15px; margin-right:20px">By User {{Comment.Id}}</h2>
<h2 class="pull-right" style="color: darkviolet; font-size: 15px; margin-right: 20px">{{Comment.LastUpdateTime.slice(6,-2) | date: 'hh:mm a dd-MMM-yyyy' }}</h2>
<div class="clearfix"> </div>
<hr />
</div>
</div>
</div>
<div class="col-sm-10" style="font-size:17px">
<form novalidate name="f1" ng-submit="AddComment()">
<div style="color: red">{{Message}}</div>
<div class="col-sm-1">
<div class="glyphicon glyphicon-plus" style="height: 50px;border:1px solid; width: 50px; cursor:pointer;" onclick="getFile()">
<div style="height: 0px;width:0px; overflow:hidden;">
<input id="filesel" type="file" name="file" accept="image/*" onchange="angular.element(this).scope().selectFileforUpload(this.files)" required multiple />
</div>
</div>
<span class="error">{{FileInvalidMessage}}</span>
</div>
<div class="col-sm-6 pull-left">
<input type="text" placeholder="Enter Your Comment Here" style="height: 50px;font-size:30px;width:500px" name=" ufiledescription" ng-model="CommentText" class="{{(IsFormSubmitted?'ng-dirty' + (f1.uFileDescription.$invalid?' ng-invalid':''):'')}}" autofocus />
</div>
<div class="col-sm-3 pull-left">
<input class="btn btn-primary" style="height:50px;width:100px" value="Send" id="Submit" type="submit" />
</div>
</form>
</div>
</div>
my angular controller
app.controller("MyController", function ($scope, MyServices,$http) {
// Get All Comments
GetAllComments();
function GetAllComments() {
var getData = MyServices.getComments();
getData.then(function (cmnt) {
$scope.Comments = cmnt.data;
},
function () {
alert('Error in getting Comments');
});
};
// Add New Comment
$scope.AddComment = function () {
var Comment = {
CommentText: $scope.CommentText
};
var getData = MyServices.AddCmnt(Comment);
getData.then(function (ResultMsg) {
GetAllComments();
alert(ResultMsg.data);
});
ClearFields();
$scope.refresh();
};
// Edit The Comment
$scope.EditComment = function () {
Comment =
{
Id: Comment.Id,
CommentText: $scope.UpdateCommentText
}
alert(Comment.CommentText);
//var getData = MyServices.getCommentById(Comment.Id);
var getData = MyServices.EditCmnt(Comment);
getData.then(function (ResultMsg) {
alert(ResultMsg.data);
GetAllComments();
});
};
// Delete The Comment
$scope.RemoveComment = function (Comment) {
var getData = MyServices.DeleteCmnt(Comment);
getData.then(function (ResultMsg) {
alert(ResultMsg.data);
GetAllComments();
},
function () {
alert('Error in Deleting Comment');
});
}
//Clear Fields After Comment Addition
function ClearFields() {
$scope.CommentText = "";
angular.forEach(angular.element("input[type='file']"), function (inputElem) {
angular.element(inputElem).val(null);
});
};
});
in the index page the comment.commenttext which is editable text and coming from database on click of edit there will be a editable text box and after editing the text on click of save button i cant get value of edited text what shpold to in editcomment section to retrieve value of edited text?
i tried $scope.Comment.commenttext but it is undefined..
help me thanks in advance..
You have a double bind here:
<h3>
<text
style="color:mediumpurple;"
e-form="rowform"
data-ng-model="UpdateCommentText"
editable-text="Comment.CommentText"
>
{{Comment.CommentText || 'Empty'}}
</text>
</h3>
So basically you see what is binded with data-ng-model, not experssion in {{ }} Try getting UpdateCommentText value. Maybe this helps.