Passing "Id" selected checkbox to Modal bootstrap and send to controller - javascript

I have a list of Articles and I want to have a possibility to delete selected articles or all articles in a modal popup window. Also, I have checkboxes in my View. My idea - get an "Id" of each selected article, passing these articles to modal bootstrap popup. After, using form-action Post will send these "Id" to action controller method for further actions. (public ActionResult DeleteArticle (FormCollection fc){}).
I want to understand how I can pass "Id" of selected with checkboxes Articles to modal Bootstrap popup. Thanks!
My ListOfArticls.cshtml:
<table class="table table-striped table-hover">
<thead>
<tr>
<th>
<span class="custom-checkbox">
<input type="checkbox" id="checkBoxAll">
<label for="selectAll"></label>
</span>
</th>
<th>#Html.DisplayNameFor(model => model.Title)</th>
<th>#Html.DisplayNameFor(model => model.PublishDate)</th>
<th>#Html.DisplayNameFor(model => model.Tag)</th>
<th>#Html.DisplayNameFor(model => model.Note)</th>
<th>#Html.DisplayName("Category name")</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
<span class="custom-checkbox">
<input type="checkbox" class="chkCheckBoxId" value="#item.Id">
<label for="chkCheckBoxId"></label>
</span>
</td>
<td>
#Html.ActionLink(Html.DisplayFor(modelItem => item.Title).ToHtmlString(), "ArticleDetails", new { id = item.Id })
</td>
<td>
#Html.DisplayFor(modelItem => item.PublishDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Tag)
</td>
<td>
#Html.DisplayFor(modelItem => item.Note)
</td>
<td>
#Html.DisplayFor(modelItem => item.Category.Name)
</td>
<td>
<i class="material-icons" data-toggle="tooltip" title="Edit"></i>
<i class="material-icons" data-toggle="tooltip" title="Delete"></i>
</td>
</tr>
}
</tbody>
</table>
<script type="text/javascript">
$(document).ready(function () {
$('#checkBoxAll').click(function () {
if ($(this).is(":checked")) {
$(".chkCheckBoxId").prop("checked", true)
}
else {
$(".chkCheckBoxId").prop("checked", false)
}
});
});
</script>
Popup:
<!-- Delete Modal HTML -->
<div id="deleteArticleModal" class="modal fade">
<div class="modal-dialog">
<input type="hidden" id="linkId" />
<div class="modal-content">
<form action="#Url.Action("DeleteArticle", "Post")" method="post">
<div class="modal-header">
<h4 class="modal-title">Delete Employee</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete these Records?</p>
<p class="text-warning"><small>This action cannot be undone.</small></p>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel" onclick="deleteConfirm()">
<input type="submit" class="btn btn-danger" value="Delete">
</div>
</form>
</div>
</div>
</div>
Controller:
[HttpPost]
public ActionResult DeleteArticle(FormCollection fc)
{
// Some code
return RedirectToAction("ListOfArticles");
}
UPDATE:
Little bit corrected:
js
// loop through all the check boxes
$("input[type=checkbox]:checked").each(function () {
and my controller:
[HttpPost]
public ActionResult DeleteArticle(FormCollection fc)
{
var values = fc["articlesArray"];
string[] str = values.Split(',');
for(int i=0; i < str.Length; i++)
{
postService.DeleteArticleDTO(Int32.Parse(str[i]));
}
return RedirectToAction("ListOfArticles");
}

If I understand this correctly, you want to multi-select through check boxes and clicking "Delete" on any of the row's delete buttons will open the popup with the ID's of the selected articles.
You got this part correct; the checkbox input field with ID as its value.
<input type="checkbox" class="chkCheckBoxId checkbox" value="#item.Id">
Next what we want to do is loop through all the check boxes whenever the delete button is clicked.
During the loop, we will identify which ones are checked and add them to the form tag of your modal.
Add the new script below to your code, read the comments as well.
<script type="text/javascript">
$(document).ready(function () {
$('#checkBoxAll').click(function () {
if ($(this).is(":checked")) {
$(".chkCheckBoxId").prop("checked", true)
}else{
$(".chkCheckBoxId").prop("checked", false)
}
});
// bind this event to all delete buttons
$(".delete").click(function(){
// find the modal body
var modal = $("#deleteArticleModal").find(".modal-body");
// loop through all the check boxes (class checkbox)
$(".checkbox").each(function(index){
// if they are checked, add them to the modal
var articleId = $(this).val();
if($(this).is(":checked")){
// add a hidden input element to modal with article ID as value
$(modal).append("<input name='articlesArray' value='"+articleId+"' type='hidden' />")
}
});
});
});
</script>
In your form collection, the values will be passed with the property name articlesArray. It will be an array so be sure to loop through it with foreach.

Related

Adding Dynamic buttons to display pop-up window to link entries

I am creating a list of entries each with a Link button in a foreach loop on my Razor Page. The Link button is clicked to open a modal with another list of entries and all of these entries have a checkbox. This view allows me to Link an entry to multiple other entries. Code below for HTML:
#foreach (var entry in Model.EntryList.Where(w => w.IsLinked == false))
{
<tr>
<td class="pt-3-half" contenteditable="true">#entry.Description</td>
<td class="pt-3-half" contenteditable="true">
<button id="btnShowModal" type="button" class="btn btn-sm btn-default pull-left col-lg-11 button button4">
Link
</button>
<div class="modal fade" tabindex="-1" id="loginModal"
data-keyboard="false" data-backdrop="static">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Link Entries</h4>
<button type="button" class="close" data-dismiss="modal">
×
</button>
</div>
<form enctype="multipart/form-data" asp-controller="Home" asp-action="Index" asp-route-id="#entry.Description" method="post" class="mt-3">
<div class="modal-body">
<table style="text-align: center; width: 100%">
<thead>
<tr>
<th class="text-center">Description</th>
<th class="text-center"></th>
</tr>
</thead>
<tbody>
#foreach (var LinkEntry in Model.EntryList.Where(w => w.IsLinked == true))
{
<tr>
<td class="pt-3-half" contenteditable="true">#LinkEntry.Description</td>
<td class="pt-1-half" contenteditable="true">
<input name="AreChecked" type="checkbox" value="#LinkEntry.Id" />
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary button button4">Link Entries</button>
<button type="button" id="btnHideModal" class="btn btn-primary button button4">
Hide
</button>
</div>
</form>
</div>
</div>
</div>
</tbody>
</table>
</div>
</td>
</td>
</tr>
}
When the Link button is clicked the below jQuery runs:
<script type="text/javascript">
$(document).ready(function () {
$("#btnShowModal").click(function () {
$("#loginModal").modal('show');
});
$("#btnHideModal").click(function () {
$("#loginModal").modal('hide');
});
});
</script>
The current problem I have is that only the first Link button shows the Modal div. The rest of the Link buttons do not do anything when clicked. So I then moved the entire Modal Div outside of the foreach but does not fix the problem and this then also doesn't allow me to parse the asp-route-Id due to now being outside the foreach.
The issue here is that you are using hard-coded ids for your buttons, but they are created in a loop so more than one element with the same id is created, which you definitely do not want.
Remove the ids and replace them with a unique class, like btn-show-modal, then change your jquery selector from $("#btnShowModal") to $(".btn-show-modal").
Do the same thing with your hide buttons, but use a different unique class name like btn-hide-modal. Be sure to do this with all hard-coded ids (looks like there is at least one more instance).
One other point I should make is you will need to query the modal relative to the button that is clicked. Inside the click events, you should do $(this).next().modal('show') / $(this).next().modal('hide') , since as stated, you need to remove the id="loginModal" and will need an alternative method to get the correct modal to show.
I believe jquery is smart enough to not search the entire DOM when using the id selector (#), so that is why only your first button is firing your click event.
My suggestion to future proof these kinds of errors is to create a <script> that will search the DOM for duplicate ids and show an alert(), or something, to let you know that your DOM is invalid. I'd also make sure that this script is only added when debugging, as with this <script> you will catch the errors during development and do not want to the extra overhead in production.
Yes as William says, you have that error because you are using an id and that button is being created so many times as items you have in your collection. And if I was you I'll put the modal outside the first loop because otherwise you can create a lot of modal too. I leave you an example of something that I hope can help you.
This is the model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace HelloWorldMvcApp
{
public class SampleViewModel
{
[Required]
[MinLength(10)]
[MaxLength(100)]
[Display(Name = "Ask Magic 8 Ball any question:")]
public string Question { get; set; }
//See here for list of answers
public string Answer { get; set; }
public List<Test> EntryList { get; set; }
}
public class Test {
public int Id { get; set; }
public string Description { get; set; }
public bool IsLinked { get; set; }
}
}
Here you are the controller:
using System;
using System.Web.Mvc;
using System.Collections.Generic;
namespace HelloWorldMvcApp
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
var list = new SampleViewModel();
list.EntryList = new List<Test>();
var test1 = new Test();
test1.Id = 1;
test1.Description = "test1";
test1.IsLinked = false;
list.EntryList.Add(test1);
var test2 = new Test();
test2.Id = 2;
test2.Description = "test2";
test2.IsLinked = false;
list.EntryList.Add(test2);
var test3 = new Test();
test3.Id = 3;
test3.Description = "test3";
test3.IsLinked = false;
list.EntryList.Add(test3);
var test11 = new Test();
test11.Id = 11;
test11.Description = "test11";
test11.IsLinked = true;
list.EntryList.Add(test11);
var test12 = new Test();
test12.Id = 12;
test12.Description = "test12";
test12.IsLinked = true;
list.EntryList.Add(test12);
var test21 = new Test();
test21.Id = 21;
test21.Description = "test21";
test21.IsLinked = true;
list.EntryList.Add(test21);
var test22 = new Test();
test22.Id = 22;
test22.Description = "test22";
test22.IsLinked = true;
list.EntryList.Add(test22);
return View(list);
}
}
}
And this is the view.
#model HelloWorldMvcApp.SampleViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<!-- template from http://getbootstrap.com/getting-started -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<!-- CSS Includes -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style type="text/css">
.field-validation-error {
color: #ff0000;
}
</style>
</head>
<body>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<table>
<tbody>
#foreach (var entry in Model.EntryList.Where(w => w.IsLinked == false))
{
<tr>
<td class="pt-3-half" contenteditable="true">#entry.Description</td>
<td class="pt-3-half" contenteditable="true">
<button type="button" onClick="showModal('#entry.Description')" class="btn btn-sm btn-default pull-left col-lg-11 button button4">
Link
</button>
</td>
</tr>
}
</tbody>
</table>
<div class="alert alert-warning fade">
<img src="http://entechprod.blob.core.windows.net/dotnetfiddle/morpheus.jpg"
style="max-width:100%;" /><br /><br />
<strong><span class="alert-content"></span></strong>
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" id="loginModal" data-keyboard="false" data-backdrop="static">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Link Entries</h4>
<button type="button" class="close" data-dismiss="modal">
×
</button>
</div>
<form enctype="multipart/form-data" id="modalForm" asp-controller="Home" asp-action="Index"
asp-route-id="" method="post" class="mt-3">
<div class="modal-body">
<table style="text-align: center; width: 100%">
<thead>
<tr>
<th class="text-center">Description</th>
<th class="text-center"></th>
</tr>
</thead>
<tbody>
#foreach (var LinkEntry in Model.EntryList.Where(w => w.IsLinked == true))
{
<tr>
<td class="pt-3-half" contenteditable="true">#LinkEntry.Description</td>
<td class="pt-1-half" contenteditable="true">
<input name="AreChecked" type="checkbox" value="#LinkEntry.Id" />
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary button button4">Link Entries</button>
<button type="button" onClick="hideModal()" class="btn btn-primary button button4">
Hide
</button>
</div>
</form>
</div>
</div>
</div>
<!-- JS includes -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
function showModal(desc) {
$('#modalForm').attr('asp-route-id', desc);
$("#loginModal").modal('show');
}
function hideModal(desc) {
$("#loginModal").modal('hide');
}
</script>
</body>
</html>
Creating a modal for each entry in the loop seems unnecessary to me,
Create a single modal outside your loop and update all its data according with the Link button you clicked
Use data- attributes to pass the info you require to the click event and to build/update your modal, you can JSON your info and use a javascript function to create the table and checkboxes bit
#foreach (var entry in Model.EntryList.Where(w => w.IsLinked == false))
{
<tr>
<td class="pt-3-half" contenteditable="true">#entry.Description</td>
<td class="pt-3-half" contenteditable="true">
<button data-entry-id="#entry.Id" data-entries="<?= htmlentities(json_encode(Model.EntryList.Where(w => w.IsLinked == true)))?>" id="btnShowModal" type="button" class="btn btn-sm btn-default pull-left col-lg-11 button button4 ">
Link
</button> ...
then you add a listener with JS to all those Link buttons
function onClickLinkButtonUpdateModal($e){
let entries = JSON.parse($e.target.dataset.entries);
let entry_id = $e.target.dataset.entryId;
//pass the info you need, you can create the tr elements or the whole tbody with document.create or with template literals
let tr_entries = generateHTMLEntries(entry_id, entries);
//assuming you put an id to the table or the table body
document.querySelector('#modal-table').appendChild(tr_entries);
//or
//document.querySelector('#modal-tbody').innerHTML = tr_entries;
}

Razor: button click not fired correctly

I have a view. I want to load it to get all information then click Edit or Delete button to do something. When click Edit button then I hope it goes to another view.
#model Models.CountryLanguagesModel
#{
ViewBag.Title = "Language";
}
<div class="span4 proj-div text-center" data-toggle="modal" data-target="#addLanguageModal">
<u>Add Language</u>
<div><br /> </div>
<table class="table table-bordered table-dark-header table-responsive">
<tr>
<th class="text-center">Language Name</th>
<th class="text-center">Welcome Message</th>
<th></th>
</tr>
#foreach (var item in Model.CountryLanguages)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.LanguageName)</td>
<td>#Html.DisplayFor(modelItem => item.WelcomeMessage)</td>
</tr>
}
</table>
</div>
<div class="container">
<div class="col-md-8 col-md-offset-2">
<button class="btn btn-success" id="editLanguage">Edit</button>
<button class="btn btn-danger" id="deleteLanguage">Delete</button>
</div>
</div>
<div class="modal fade" id="addLanguageModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Add Language</h3>
</div>
<div class="modal-body">
<div class="form-group">
</div>
<div class="form-group">
<div class="left">
<label>Language Name:</label>
</div>
<div class="right">
<input type="text" class="form-control" name="languageName" id="languageName" />
</div>
</div>
<div class="form-group">
<div class="left">
<label>Welcome Messagee:</label>
</div>
<div class="right">
<input type="text" class="form-control" name="welcomeMessage" id="welcomeMessage" />
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-gray" data-dismiss="modal" aria-hidden="true">Close</button>
<button class="btn btn-primary" id="addLanguageBtn">Save</button>
</div>
</div>
</div>
</div>
#section scripts
{
<script type="text/javascript">
$(document).ready(function () {
$("#addLanguageBtn").on("click", function (evt) {
var CountryId = #Model.CountryId;
var languageName = $("#languageName").val();
var welcomeMessage = $("#welcomeMessage").val();
$.post("/Country/AddLanguage", { id: CountryId, languageName: languageName, welcomeMessage: welcomeMessage }, function (data) {
$("#languageName").val("");
$("#welcomeMessage").val("");
$("#addLanguageModal").modal('hide');
});
});
$("#editLanguage").on("click", function (evt) {
var CountryId = #Model.CountryId;
$.post("/Country/LanguageEdit", { id: CountryId }, function () {
});
});
$("deleteLanguage").on("click", function (evt) {
var CountryId = #Model.CountryId;
$.post("/Country/LanguageDelete", { id: CountryId }, function () {
});
});
});
</script>
}
Now the question is when the page loaded, I found the the code reached click event script. It is strange. When I click the button, it doesn't reach the script. But it goes to the controller action method,
[HttpPost]
public ActionResult LanguageEdit(MyModel model)
{
I guess some stupid error to cause the onclick event not fired correctly, but I can't figure it out.
EDIT
public ActionResult LanguageEdit(int id)
{
var model = new CountryLanguageModel();
model.CountryId = id;
model.CountryLanguageQuestion = MyService.GetQuestion(x => x.CountryId == id);
return View(model);
}
Add type='button' attribute to your buttons, if not it will behave as a submit button.
can you change button to a ?
<button class="btn btn-success" id="editLanguage">Edit</button>
to
<a href="/Country/LanguageEdit?id=#Model.CountryId" class="btn btn-success" />
Some more information
if you want to GET somekind of HTML use HTTPGET instead of HTTPPOST.
Use HTTPPOST if you want to send some kind of information, that server should for example save. Use HTTPGET if you want to render some kind of view ( for example get a new view),
Your Action required 'MyModel model' not a id.
As per your comment you may get this behaviour:
why it was fired when page loaded, I didn't click the button at all.
When your javascript code not inside the button click event and instead it is inside any of the other event such document ready or page load ..etc.
So kindly check the event of javascript and surely you will get the direction to solution .
After checked ,If you ,still had the same problem. kindly show us your javascript so that it will be useful to help you further
Thanks
Karthik

How do i pass the ID of row to Modal?

I have Edit button on each row. If I press Edit button on selected row I need pass ID of this row to Modal and use it in sql query to call rest of data. P.S. I tried many ways, no one of them helped and based on bootstrap.
Here is my code with Modal
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container">
<div class="table-responsive">
<table class="table" id="myTable">
<thead>
<tr class="header">
<th>#</th>
<th>Müştərinin Nömrəsi</th>
<th>Götürülən Ünvan</th>
<th>Gədilən Ünvan</th>
<th>Zəng Vaxtı</th>
<th>Sürücünün Tabel Kod</th>
<th>Təhfil aldı</th>
<th>Təhfil verdi</th>
<th>Maşın Nömrəsi</th>
<th>Qiymət</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php
while($data=mysql_fetch_array($result)) // цикл вывода
{
$id = $data['id'];
echo "<tr>
<td></td>
<td>".$data['MUSHTERINOMRE']."</td>
<td>".$data['MUSHTERIHARDAN']."</td>
<td>".$data['MUSHTERIHARA']."</td>
<td>".$data['ZENGVAXTI']."</td>
<td>".$data['TABELKOD']."</td>
<td>".$data['TEHFILALDI']."</td>
<td>".$data['TEHFILVERDI']."</td>
<td>".$data['MASHINNOMRE']."</td>
<td>".$data['QIYMET']."</td>
<td><button class=\"btn btn-success\" onclick='getValue(".$id.");' data-toggle=\"modal\" data-target=\"#myModal\" contenteditable=\false\" value=".$id.">EDIT </button></td>
"; ?>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content"></div>
</div>
<div class="modal-dialog">
<div class="modal-content"></div>
</div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"> <span aria-hidden="true" class="">? </span><span class="sr-only">Close</span>
</button>
<!--Here I am trying to echo ID
<h4 class="modal-title" id="myModalLabel"><?php //echo $id."ID OFaa"; ?></h4>-->
</div>
<div class="modal-body">
<?php echo $id."I NEED TO GET ID HERE "; ?>
<?php
$link = mysql_connect('localhost', 'user', 'psw');
$db_selected = mysql_select_db('my_db', $link);
$query = mysql_query("Select * from my_table where id = $id");
//var_dump($pt);
$row = mysql_fetch_array($query);
$number = $row['num'];
?>
<div class="form-group">
<label for="name" class="control-label">Müştəri Nömrə:</label>
<input type="text" class="form-control" id="num" name="num" value="<?php echo $number; ?>" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
The most important thing to remember is that PHP won't execute client-side, so populating the dialog with id and editable values must be performed by the client-side language - javascript. Your only option for further server-side involvement during the editing process is to make AJAX call(s).
You will find the process a lot simpler with a "promisified" modal dialog. Rather than write something yourself, you can install install, bootStrapModal, giving you a modal that is much like the standard Bootstrap modal but behaves as an asynchronous resource.
HTML:
<script src="js/bsBetterModal.js"></script>
Build the table rows as follows :
while($data=mysql_fetch_array($result)) { // цикл вывода
$id = $data['id'];
echo "<tr data-id=\".$id.\">
<td></td>
<td class=\"mushterinomre\">".$data['MUSHTERINOMRE']."</td>
<td class=\"mushterihardan\">".$data['MUSHTERIHARDAN']."</td>
<td class=\"mushterihara\">".$data['MUSHTERIHARA']."</td>
<td class=\"zengvaxti\">".$data['ZENGVAXTI']."</td>
<td class=\"tabelkod\">".$data['TABELKOD']."</td>
<td class=\"tehfilaldi\">".$data['TEHFILALDI']."</td>
<td class=\"tehfilverdi\">".$data['TEHFILVERDI']."</td>
<td class=\"mashinnomre\">".$data['MASHINNOMRE']."</td>
<td class=\"qiymet\">".$data['QIYMET']."</td>
<td><button class=\"btn btn-success edit\">EDIT</button></td>
</tr>";
} ?>
...
Write the dialog's header as follows :
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"> <span aria-hidden="true" class="">? </span><span class="sr-only">Close</span></button>
<h4 class="modal-title dlg-element" data-element="id"></h4>
</div>
Write each of the dialog's inputs (x8) as follows :
<label class="control-label">Müştəri Nömrə:</label>
<input type="text" class="dlg-element" data-element="mushterinomre" value="" />
Write the dialog footer as follows :
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary ok">Save changes</button>
</div>
The EDIT buttons' click handler is a little complicated. It comprises some preamble followed by a promise chain. I've made it as simple as I can by unloading the fiddly bits into a bunch of helper utilities.
jQuery(function($) {
// *** start: click handler ***
$('#myTable').on('click', '.edit', function(e) {
e.preventDefault(); // in case button attempts form submission
var $button = $(this).prop('disabled', true);
var $row = $(this).closest('tr');
var idHash = { 'id': $row.data('id') }; // <<<<<< HERE'S THE ID - expressed as a js plain object.
// From here on, everything is asynchronous, therefore performed within a promise chain.
fetchValues(idHash) // Fetch current values (onscreen values may be stale)
.then(function(valuesHash) {
return betterModal.run($('#myModal'), $.extend(valuesHash, idHash))// Open modal window, populated with current field values.
.then(function($dialog) {
// The dialog was accepted.
// `$dialog` holds a jQuery object of the dialog.
return saveValues($.extend(dialogToHash($dialog), idHash)); // Pass hash of editable field values, plus idHash, to saveValues()
})
.then(function() {
// New values were successfully saved.
// valuesHash is still in scope
updateHtmlTableRow($row, valuesHash); // Update the HTML table row with the edited values.
}, function(err) {
// Save failed
// Provide warning to user ...
return err;
})
})
.then(null, function(err) {
console.log(err);
$button.prop('disabled', false);
})
.always(function() {
$button.prop('disabled', false);
});
});
// *** end: click handler ***
var fields = ['mushterinomre', 'mushterihardan', 'mushterihara', 'tabelkod', 'tehfilaldi', 'tehfilverdi', 'mashinnomre', 'qiymet']; // 'zengvaxti' omitted
// *** start: helper utility functions ***
function fetchValues(idHash) {
return $.getJSON({
'url': 'api.php', // replace with actual url
'method': 'get',
'data': idHash
});
}
function saveValues(values) {
return $.ajax({
'url': 'api.php', // replace with actual url
'method': 'put',
'data': values
});
}
function dialogToHash($dialog) {
var hash = {};
fields.forEach(function(f) {
hash[f] = $('.'+f, $dialog).val();
});
return hash;
}
function updateHtmlTableRow($row, valuesHash) {
fields.forEach(function(f) {
$('.'+f, $row).text(valuesHash[f]),
});
}
// *** end: utility functions ***
});
Untested and sketchy in places so will need debugging. Some server-side stuff also needs to be addressed.
Hope this gives you some direction
function getValue(id)
{
$.ajax({
url:'filename.php',
method:'get',
data:'id='+id,
success: function(ret)
{
// add the returned value into the modal body
$('#modalBody').html(ret);
// show the modal
$('#myModal').show();
}
});
}

How to use multiple submit buttons with Razor MVC 5.2.3 Ajax

I have a view which calls a partial view via ajax. The partial view has a table which is contained in another ajax form. Each row contains two submit buttons that I wish to map to two different actions, Save and Delete. However, when I submit either button, no data gets passed to the controller. The String submitAction and ProjectComment projectcomment contains no data comment data from the form. I have the following code:
MyView:
Index.cshtml
#model MyProject.Areas.MyComments.Models.ProjectComment
#using (Ajax.BeginForm("Details", null,
new AjaxOptions
{
HttpMethod = "POST", // HttpPost
InsertionMode = InsertionMode.Replace, // empty the target first
UpdateTargetId = "commentTbl" // place content within #commentTbl
}, new { #class = "form-inline" }))
{
#Html.AntiForgeryToken()
<p>...</p>
<div class="ibox float-e-margins">...</div>
}
<div id="commentTbl">...Partial View is loaded here...</div>
Partial View
Details.cshtml
#model IEnumerable<MyProject.Areas.MyComments.Models.ProjectComment>
#using (Ajax.BeginForm("Update", null,
new AjaxOptions
{
HttpMethod = "POST", // HttpPost
InsertionMode = InsertionMode.Replace, // empty the target first
UpdateTargetId = "commentTbl" // place content within #commentTbl
}, new { #class = "form-inline" }))
{
<div class="ibox float-e-margins">
<div class="ibox-title">...</div>
<div class="ibox-content">
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover dataTables-example" id="dataTables-comments">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Comment)
</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#{int i = 0;}
#foreach (var projectcomment in Model)
{
<tr>
<td>
#Html.EditorFor(modelItem => projectcomment.Comment)
</td>
<td>
<button type="submit" id="save" class="btn btn-primary" name="Save" value='#i'>Save</button>
<button type="submit" id="delete" class="btn btn-primary" name="Delete" value='#i'>Delete</button>
</td>
</tr>
i++;
}
</tbody>
</table>
</div>
</div>
</div>
}
My Controller
CommentController.cs
[HttpPost]
public ActionResult Update(ProjectComment projectcomment, String submitAction)
{
// submitAction is null and projectcomment contains no form data.
if (submitAction.Equals("Save"))
return RedirectToAction("Save", projectcomment);
else if (submitAction.Equals("Delete"))
return RedirectToAction("Delete", projectcomment);
else
return HttpNotFound();
}
[HttpPost]
public ActionResult Save([Bind(Include="Comment")] ProjectComment projectcomment)
{
// ... to do logic here
}
Please help with what I am doing wrong.
Modify you button name to match your parameter name. For example:
Your Code:
<button type="submit" id="save" class="btn btn-primary" name="Save" value='#i'>Save</button>
<button type="submit" id="delete" class="btn btn-primary" name="Delete" value='#i'>Delete</button>
What it should be:
<button type="submit" id="save" class="btn btn-primary" name="submitAction" value='Save'>Save</button>
<button type="submit" id="delete" class="btn btn-primary" name="submitAction" value='Delete'>Delete</button>
I modified the name to match your parameter name and value you are accepting in your controller. When you submit the form, you will now be passing the value to your parameter.

Angular error : Expected array but received: 0

I'm getting this error when I open up a model partial:
<form action="" novalidate name="newGroupForm">
<div class="modal-body">
<div class="row">
<!-- SELECT THE NUMBER OF GROUPS YOU WANT TO CREATE -->
<label>Select number of groups</label>
<a class="btn" ng-click="newGroupCount = newGroupCount + 1" ng-disabled="newGroupCount == 10" ><i class="fa fa-plus-circle"></i></a>
<input class="groupCounter input-sm" ng-model="newGroupCount" type="number" min="1" max="10" disabled>
<a class="btn" ng-click="newGroupCount = newGroupCount - 1" ng-disabled="newGroupCount == 1"><i class="fa fa-minus-circle"></i></a>
</div>
<br>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Group Name</th>
<th>Group Description (optional)</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="i in getNumber(newGroupCount) track by $index">
<td>{{$index+1}}</td>
<td>
<input class= input-sm type="text" required="true" autofocus="true" placeholder="Group name" ng-model="groupData.title[$index]">
</td>
<td>
<input class="form-control input-sm" type="textarea" ng-model="groupData.desc[$index]" placeholder="Group Description">
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<button class="btn btn-primary" type="submit" ng-click="submit()" ng-disabled="newGroupForm.$invalid">Create</button>
</div>
</form>
The modal controller looks like this:
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $uibModalInstance, GroupService){
$scope.groupData = {
title: [],
desc: []
}
$scope.newGroupCount = 1;
$scope.getNumber = function(num) {
//console.log(num);
return new Array(num);
}
$scope.submit = function(){
$uibModalInstance.close($scope.groupData);
}
$scope.cancel = function (){
$uibModalInstance.dismiss('Cancelled group creation');
};
}
);
Every question I've seen refers to the use of filterbut I'm not using filter. The error repeats whenever I hit the increment button:
<a class="btn" ng-click="newGroupCount = newGroupCount + 1" ng-disabled="newGroupCount == 10" ><i class="fa fa-plus-circle"></i></a>
$scope.getNumber calls new Array(num), which will return an array of undefined values directly proportional to the value of newGroupCount.
For example:
new Array(5) // => [undefined, undefined, undefined, undefined, undefined]
Browsers don't handle that well, since it appears to be an empty array.
You're using ng-repeat in a way that it wasn't quite meant to be used. If I were you, I'd refactor to look something like this:
$scope.groups = [];
$scope.addGroup = function() {
// implement this, and use it in your button that increments the groups
$scope.groups.push(/* whatever */);
}
$scope.removeGroup = function() {
// implement this to remove a group
$scope.groups.splice(/* whatever */);
}
Then in your HTML:
<tr ng-repeat="group in groups">
<!-- display group info -->
</tr>
It may make your life easier here to work with angular (use it how it was intended) instead of fighting against how ng-repeat is meant to work.
The data is generally meant to be in the form of a collection (i.e. [{},{},{}]). Formatting it as such will make it easier for you. See the docs for ng-repeat.

Categories

Resources