Basically what I want to do is:
Click on a button to delete a record.
Delete the record if a specific column (Location) is null (this is done and works fine)
Delete the record, BUT if the specific column is not null, ask the user to confirm.
So step 3 is the tricky part. With the AJAX, I call the deleteChannel(url) that you see below, which calls the proper method in code-behind. Now here is the tricky part:
if (channel != null && channel.Location != null)
{
// How do I do this? (Notice that this is code-behind)
ShowDialogThatAsksUserToConfirm()
}
The code: ShowDialogThatAsksUserToConfirm() needs to call back to the client saying that "The Location column is not null", and wait for user to say delete anyway, or cancel.
I have this code that will call a method in code behind:
function deleteChannel(url) {
$.ajax({
url: url,
type: "POST",
cache: false,
contentType: 'application/html; charset=utf-8',
data: $("form").serialize(),
dataType: 'html',
success: function (msg) {
showDialog('successDiv');
},
error: function (msg) {
alert("error");
showDialog('errorDiv');
}
});
}
And the showDialog(...) looks like this:
function showDialog(divID) {
$("#" + divID).dialog({
show: "clip",
hide: "clip",
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
});
}
The code-behind looks like this:
[HttpPost]
public ActionResult DeleteChannel(int id)
{
var statusCode = new HttpStatusCode();
using (var context = new MaaneGrisContext())
{
var channel = context.Channels.FirstOrDefault(x => x.ID == id);
if (channel != null && channel.Location != null)
{
if (Confirmation()) //The Confirmation() method not implemented yet, but it should ask user to confirm
{
context.Channels.Remove(channel);
context.SaveChanges();
List<ChannelModel> updatedChannelList = new List<ChannelModel>();
context.Channels.AddRange(context.Channels);
return View("ChannelDetails", updatedChannelList);
}
}
}
Here is the View:
<table style="border: ridge 1px">
<tr>
<th>Name</th>
...
</tr>
#{
foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(m => item.ChannelName)</td>
<td>#Html.DisplayFor(m => item.Description)</td>
<td>#Html.DisplayFor(m => item.Unit)</td>
<td>#Html.DisplayFor(m => item.Location.StableName)</td>
<td>#Html.DisplayFor(m => item.CreationDate)</td>
<td>#Html.DisplayFor(m => item.LastEdited)</td>
<td>#Html.DisplayFor(m => item.ExtraNote)</td>
<td><span class="glyphicon glyphicon-copy"></span></td>
<td><span class="glyphicon glyphicon-edit"></span></td>
<td><a href="#" onclick="deleteChannel('#Url.Action("DeleteChannel", "Channel", new { id = item.ID })')">
<span class="glyphicon glyphicon-remove"></span></a>
</td>
</tr>
}
}
</table>
<br/><br/>
<div style="display: none;">
#* #{ Html.RenderPartial("_CreateChannel"); } *#
</div>
<h5>#Html.ActionLink("Opret en ny kanal", "RegisterChannel", "Channel")</h5>
<div id="cautionDiv" title="Bekræft sletning" style="display: none;">
<p style="color: red;">The channel has a location. Are you sure you want to delete?</p>
</div>
<div id="successDiv" title="Info" style="display: none;">
<p style="color: green;">Deleted</p>
</div>
This is just my approach, and is not final, if there are better solutions, please let me know
You can't call js from a codebehind, but your ajax method can return an indication for asking the user:
if (channel != null && channel.Location != null)
{
return 'cannot-delete';
}
and the ajax method would see that on it's success function, and prompt the user:
$.ajax({
url: url,
type: "POST",
cache: false,
contentType: 'application/html; charset=utf-8',
data: $("form").serialize(),
dataType: 'html',
success: function (msg) {
if (msg == 'cannot-delete') {
ShowDialogThatAsksUserToConfirm();
} else showDialog('successDiv');
},
error: function (msg) {
alert("error");
showDialog('errorDiv');
}
});
The method ShowDialogThatAsksUserToConfirm should ask for the users's confirmation in javascript, and if allowed, submit a forced delete of the record.
Related
I am trying to send the data of my table with dynamic values to the controller.
<tbody>
#if (ViewBag.data != null)
{
foreach (var item in ViewBag.data)
{
<tr>
<td class="AutoId">#item.AutoID <input type="hidden" name="AutoID" value="#item.AutoID" /></td>
<td class="hove" name="text"> <b>#item.Text</b><br /><label></label></td>
<td class="Active">#item.Active</td>
<td id="oBy" name="OrderBy">#item.OrderBy</td>
</tr>
}
}
above is the table structure
I am using below ajax call to send one field for example...
<script>
$(document).ready(function () {
alert("Test 1");
$("#btnSave").click(function (e) {
alert("Test 2");
$.ajax({
type: "POST",
url: '#Url.Action("LookupManagementUpdate", "Admin", new { Area = "Admin" })',
data: $(".hove").val(),
dataType: 'json',
async: false,
success: function (response) {
Success = true;
},
error: function (response) {
},
});
});
});
</script>
Below is my controller code
public string LookupManagementUpdate(string text)
{
return "answer"+Request["text"]+text;
}
I tried using both Request and parameter method to fetch the data but it does not display the table data.
This is a c# mvc ado.net based project
try using Ajax.BeginForm and ajaxOptions Onsuccess
So I have a string that has been passed from JS to my controller like so:
JavaScript
function findEmployees(userCounty) {
$.ajax({
type: "POST",
dataType: "json",
url: '#Url.Action("getCounty", "Contact")',
data: JSON.stringify(userCounty),
contentType: "application/json",
});
}
Controller
[HttpPost]
public ActionResult Index([FromBody] string userCounty)
{
var county = userCounty.Substring(0, userCounty.IndexOf(" "));
var query = from m in _context.model where m.county == county select new Model
{
FirstName = m.Firstname
LastName = m.LastName
};
if (query == null)
{
return NotFound();
}
return View(query.ToList());
}
[HttpGet]
public ActionResult Index()
{
return View();
}
View
#model Project.Models.ModelName
<table class="table">
<tbody>
<tr>
<td>
#Html.DisplayFor(model => model.FirstName) #Html.DisplayFor(model => model.LastName)
</td>
</tr>
</tbody>
I am able to pass the string from JS to my controller and query the database but how do I update the page to show the results of the query in my view? Anything helps. Thank you!
The data returned by ajax is text or json. If you want to use c# to update the page. You can make action getCounty return partial view, partial view automatically returns data with html.
Change action getCounty.
[HttpPost("getCounty")]
public ActionResult Index([FromBody] string userCounty)
{
var county = userCounty.Substring(0, userCounty.IndexOf(" "));
//...
return PartialView(query.ToList());
}
PartialView Index.cshtml
#model List<ModelName>
<table class="table">
<tbody>
#for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(model => model[i].FirstName) #Html.DisplayFor(model => model[i].LastName)
</td>
</tr>
}
</tbody>
</table>
View
#model ModelName
<div id="datalist">
</div>
<!--other code-->
#section Scripts{
<script>
function findEmployees(userCounty) {
$.ajax({
type: "POST",
//dataType: "json",
url: '#Url.Action("getCounty", "Contact")',
data: JSON.stringify(userCounty),
contentType: "application/json",
success: function (data) {
$('#datalist').html(data)
},
error: function (e) {
console.log(e)
}
});
}
</script>
}
It can generate different data tables according to userCounty
You can get the list to the page like this.You can then press inside a div or ul list with each loop.
function findEmployees(userCounty) {
$.ajax({
type: "POST",
dataType: "json",
url: '#Url.Action("getCounty", "Contact")',
data: JSON.stringify(userCounty),
contentType: "application/json",
success: function (result) {
if (result.data.length !== 0) {
$.each(result.data, function (index, value) {
var firstName = value.firstName;
var lastName = value.lastName;
});
}
},
});
}
I have CheckBox which is working like Toggle Switches and by default it is set Checked/ON and when i UnChecked/OFF the CheckBox,it will pass the value (OFF) not problem , but when i Checked the Checkbox again it cant pass the value (ON).
Can anyone please help me or point me in the right direction!
Thanks in advance :)
Example With ScreenShots:
By Default it is set Checked/ON
Now I UnChecked/OFF , its pass the Value
Now i Checked/ON again, it cant pass the Value
View:
<tbody>
#foreach (var rma in Model)
{
<tr>
<td>
<label class="switch switch-text switch-primary switch-pill">
<input type="checkbox" class="switch-input" checked>
<span data-on="ON" data-off="OFF" class="switch-label"></span>
<span data-id="#rma.Id" class="switch-handle"></span>
</label>
</td>
</tr>
}
</tbody>
JavaScript:
<script>
$(document).ready(function () {
$('.switch-handle').click(function () {
var Id = $(this).data('id');
var checkStatus = this.checked ? 'ON' : 'OFF';
$.ajax({
type: "POST",
url: '#Url.Action("UpdateNtf", "Account")',
data: {
id: Id,
status: checkStatus
},
dataType: 'json',
success: function (result) {
if (result) {
console.log("Ok");
} else {
console.log("error");
}
},
error: function () {
console.log('something went wrong - debug it!');
}
})
});
});
</script>
Controller:
public JsonResult UpdateNtf(int? id, string status)
{
var result = db.RMA_History.Where(a => a.Id == id).FirstOrDefault();
if (result != null)
{
result.NTFOnOFF = status;
db.SaveChanges();
}
return Json(result,JsonRequestBehavior.AllowGet);
}
This is my code in Razor view that basically displays the table by extracting information from database -
#model List<EmpoyeeInfo.Models.FFX_HR_Employees>
#using System.Reflection;
#{
ViewBag.Title = "Employee Information";
var Properties = Model[0].GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
string[] head = new string[Properties.Count()];
}
<div id="web-top">
<div id="horizontal-line"></div>
<input class="search-box-text" type="text" spellcheck="false" placeholder="Search Individual Record..." title="Search Individual Record" id="searchbox" name="searchbox" />
</div>
<div id="web-main">
<table class="employee-info">
<tr>
#foreach (var Property in Properties)
{
if (Property.Name.Equals("AnnualHolidayEntitlement"))
{
<th colspan="2">#Property.Name</th>
}
else
{
<th>#Property.Name</th>
}
}
</tr>
#foreach(var Row in Model)
{
<tr>
#{
Type type = Row.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(type.GetProperties());
}
#foreach (PropertyInfo prop in props)
{
if (prop.Name.Equals("AnnualHolidayEntitlement"))
{
<td contenteditable="true">#prop.GetValue(Row, null)</td>
}
else
{
<td>#prop.GetValue(Row, null)</td>
}
}
<td class="saveToDB">SAVE</td>
</tr>
}
</table>
</div>
but as i type in the search box text, an ajax calls are made -
$(document).ready(function () {
$('.search-box-text').keypress(function () {
getReport($(this).html());
});
})
function getReport(Name) {
$.ajax({
url: '#Url.Action("Index", "Home")',
type: 'POST',
data: { Name: Name },
dataType: "json",
cache: false,
success: function (result) {
//do stuff;
},
error: function () {
console.log("no display");
}
});
}
now how do i reload the div - "web-main" and update the Model value such that as the user searches for a name, the table also needs to be updated.
Code below will append the results to the div 'web-main'. You need to manipulate the success portion of jQuery in your code
$(document).ready(function () {
$('.search-box-text').keypress(function () {
getReport($(this).html());
});
})
function getReport(Name) {
$.ajax({
url: '#Url.Action("Index", "Home")',
type: 'POST',
data: { Name: Name },
dataType: "json",
cache: false,
success: function (data) {
//do stuff;
console.log(data);
$("web-main").append(JSON.stringify(data));
},
error: function () {
console.log("no display");
}
});
}
I'm not sure how to refresh data after I use AJAX. Here's what I already have:
Frontend:
#model TFU.Model.DB_USER
<div id="listTelNumbers">
#foreach (var item in Model.DB_USER_PHONES)
{
<dl class="dl-horizontal">
<dt>
#item.PHONE
</dt>
<dd>
<button id="removeButton" class="btn btn-default" onclick="sendRequestToRemove('#item.USER_ID', '#item.PHONE')">Usuń</button>
</dd>
</dl>
}
</div>
Script - fadeOut works fine but I don't know what should I fadeIn. So I guess is missing a small part of code there.
Also how can I fadeOut only the record which I currently removing instead all list.
<script>
function sendRequestToRemove(id, phone) {
var data = {
"USER_ID": id,
"PHONE": phone
}
$.ajax({
url: '/User/RemoveTelNumber',
data: JSON.stringify(data),
type: 'POST',
contentType: 'application/json; charset=utf-8',
error: function (err) {
alert('Error: ' + err.statusText);
},
success: function (result) {
$('#listTelNumbers').fadeOut(800, function () {
form.html('#listTelNumbers').fadeIn().delay(2000);
});
},
async: true,
processData: false
});
}
</script>
Backend:
public bool RemoveTelNumber(DB_USER_PHONES model)
{
var user = db.DB_USER_PHONES.First(x => x.USER_ID == model.USER_ID && x.PHONE == model.PHONE);
db.DB_USER_PHONES.Remove(user);
db.SaveChanges();
return true;
}
Firstly, your loop is generating duplicating invalid html because of the duplicate id attributes. And you should not be polluting your markup with behavior - use Unobtrusive JavaScript. Change the html to remove the id attribute, add a class name for selection and add data-* attributes for the values to be posted
#foreach (var item in Model.DB_USER_PHONES)
{
<dl class="dl-horizontal">
<dt>#item.PHONE</dt>
<dd><button class="btn btn-default delete" data-id="#item.USER_ID" data-phone="#item.PHONE">Usuń</button></dd>
</dl>
}
Then change the script to
var url = '#Url.Action("RemoveTelNumber", "User")'; // always use Url.Action()
$('.delete').click(function() {
var container = $(this).closest('dl');
var data = { user_Id: $(this).data('id'), phone: $(this).data('phone') };
$.post(url, data, function(response) {
if (response) {
// fadeout, then remove
container.fadeOut(800, function() { $(this).remove(); })
} else {
// Oops - display an error message?
}
}).fail(function() {
// Oops
});
});
And finally, change the action method to return a JsonResult indicating success or otherwise
[HttpPost]
public JsonResult RemoveTelNumber(DB_USER_PHONES model)
{
var user = db.DB_USER_PHONES.First(x => x.USER_ID == model.USER_ID && x.PHONE == model.PHONE);
db.DB_USER_PHONES.Remove(user);
db.SaveChanges();
return Json(true);
// or if something went wrong, return Json(null);
}
I also recommend you rename you classes and properties to follow conventional naming practices - UserPhone, not DB_USER_PHONES, UserId, not USER_ID etc.
Partially reload that div
$("#listTelNumbers").load(location.href + " #dl-horizontal");
Or reload the entire page w/o refreshing it
$(document.body).load(location.href);
For a complete reference I found a demo here Partially load a div without refreshing page in javascript and php.
You can use jQuery to find the <dt> element which was marked for deletion and fade it out(or remove it completely from the DOM):
$.ajax({
url: '/User/RemoveTelNumber',
data: JSON.stringify(data),
type: 'POST',
contentType: 'application/json; charset=utf-8',
error: function (err) {
alert('Error: ' + err.statusText);
},
success: function (result) {
var dtCollection = $("dt");
for (var i = 0; i < dtCollection.length; i++) {
var text = $(dtCollection[i]).text();
text = text.trim();
if (text == phone) {
$(dtCollection[i]).parent().fadeOut('slow');
//$(dtCollection[i]).parent().remove();
}
}
},
async: true,
processData: false
});