Adding to List<Model> using JQuery - javascript

I have a ViewModel with a parameter List. In the View, the user should be able to add or remove from that list such that the added or removed users are reflected in the POST for that parameter. In JQuery, after clicking an "Add" button, an ajax call returns a UserModel variable, but a simple .append doesn't add to the list.
The other questions I've seen on this issue deal with Partial Views, but this situation updates the table of UserModel without needing a Partial View. It seems like there should be an easy way to do this. Does anyone know how to add the returned UserModel to the List in JQuery so that the List will be returned to the Post with the added models?
<script>
$("#bUser").on('click', function () {
var $addedRecipient = $("#AddedRecipient");
if ($addedRecipient.val() != null && $addedRecipient.val() != "") {
$.ajax({
type: "GET",
url: '#Url.Action("GetFullRecipient", "Message")',
data: { CompanyID: $("#CompanyID").val(), Employee: $addedRecipient.val() },
success: function (data) {
$("#Recipients").append(data);//Not adding to Recipients (Model.List<UserModel>) - is there a simple solution like this?
var bRow = $('<tr></tr>'),
bCell = $('<td style="display:none"></td>').append(data.UserID);
bRow.append(bCell);
bCell = $('<td align="center"></td>').append(data.UserFirstName);
bRow.append(bCell);
bCell = $('<td align="center"></td>').append(data.UserEmail);
bRow.append(bCell);
bCell = $('<td align="center"><input type="button" class="btn btn-info removeRecipient" value="Remove"></td>');
bRow.append(bCell);
$("#bTable tbody").append(bRow);//Works with returned data
$addedRecipient.val("");
},
error: function () {
alert("Recipient could not be added.");
}
});
}
});
</script>

this code worked perfect for me, you just have to go through this list, obviously you have to put the #model directive and a type list Recipient.
#model List<...Models.Recipient>
<input type="button" id="btnAdd" class="btn btn-primary" value="Add"
onclick="myfunction()"/>
<script>
function myfunction() {
$.ajax({
type: 'GET',
contentType:"application/json; charset=utf-8",
url: '#Url.Action("GetFullRecipient","Message")',
data: { CompanyID: $("#CompanyID").val(), Employee:
$addedRecipient.val()},
success: function (response) {
$("#containerData").html(response);
},
error: function (result) {
alert(result);
}
});
}
</script>
<div id="containerData">
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Desc_Prod</th>
<th>Cantidad</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>#item.UserID</td>
<td>#item.UserFirstName</td>
<td>#item.UserEmail</td>
<td><a class="btn btn-danger" href="#Url.Action("DeleteRow","Message", new {item.UserID})">Delete</a></td>
</tr>
}
}
</tbody>
</table>
</div>

The answer here followed the link in freedomn-m's comment. Iterate through the Razor table using a for loop, then use a HiddenFor with the model parameter's ID and a CheckBoxFor as the model parameter's selecting field, and have a submit button with a unique name and value. When a button input is clicked and the value fits a given string, loop through the model and add a user that's not there or subtract a user that is there and return to the View.
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered" id="bTable">
<thead>
<tr>
<th style="display:none"></th>
<th style="display:none"></th>
<th class="text-center">Recipient</th>
<th class="text-center">E-mail</th>
<th class="text-center">Select</th>
</tr>
</thead>
<tbody>
#if (Model.Recipients.Any())
{
for (var i = 0; i < Model.Recipients.Count; i++)
{
<tr>
<td style="display:none">#Html.HiddenFor(m => m.Recipients[i].RecipientUserID)</td>
<td style="display:none">#Html.HiddenFor(m => m.Recipients[i].RecipientCorporateID)</td>
<td align="center">#Model.Recipients[i].RecipientName</td>
<td align="center">#Model.Recipients[i].RecipientEmail</td>
<td align="center">#Html.CheckBoxFor(m => m.Recipients[i].RemoveRecipient)</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>

Related

Adding delete button to bootstrapTable in MVC

I have a .Net MVC project that fills a table with data using a bootstrapTable from bootstrap v3. I want to add a delete button to each row.
The bootstrapTable takes json data and loads it. The json is built like this:
public virtual JsonResult Search(FormCollection searchArgument)
{
IEnumerable<MyData> myListData = GetMyListData(searchArgument);
var jsonResult = Json(myListData, JsonRequestBehavior.AllowGet);
return jsonResult;
}
So the jsonResult is just a list of all of my MyData. My view that shows the result looks like this:
#model MyNamespace.Web.Models.MyListViewModel
<div class="col-md-12">
#{
ViewBag.Title = "Index";
Layout = MVC.Shared.Views._Layout;
<div class="row">
<div class="col-md-12">
<form role="form" id="formsearch">
<input id="fromsearch" name="fromsearch" type="hidden" value="true" />
<div class="form-group">
#Html.LabelFor(m => m.Status, "Status:")<br />
#Html.DropDownList("status", new SelectList(Model.Status, "Value", "Key", Model.SelectedStatus), new { #class = "selectButton" })
</div>
<input type="button" id="btnsearch" value="Search" />
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table id="table" class="table">
<thead>
<tr>
<th data-field="MyDataNumber" data-sortable="true">Number</th>
<th data-field="MyDataCreatedate" data-sortable="true">Created</th>
<th data-field="Status" data-sortable="true">Status</th>
</tr>
</thead>
</table>
</div>
</div>
}
</div>
<script>
$("#btnsearch").click(function () {
$('#table').bootstrapTable('showLoading');
$.ajax({
type: "POST",
url: "#Url.Action(MVC.MyController.ActionNames.Search, MVC.MyController.Name)",
data: $('#formsearch').serialize(),
dataType: "json",
success: function (data) {
$('#table').bootstrapTable('hideLoading');
$('#table').bootstrapTable({
data: data,
striped: true,
pagination: true,
pageSize: 25,
pageList: [10, 25, 50, 100, 200],
search: false
});
$('#table').bootstrapTable('load', data).on('click-row.bs.table', function (e, row, $element) {
Showdetail(JSON.stringify(row));
});
},
error: function (err) {
console.log(err)
}
});
});
function Showdetail(jsonrow) {
var obj = JSON.parse(jsonrow);
window.location = "#Url.Action(MVC.MyController.ActionNames.ShowMyData, MVC.MyData.Name)?myDataId=" + obj.Id;
}
</script>
#section AddToHead
{
#Styles.Render("~/bundles/bootstrap-table/css")
}
#section scripts
{
#Scripts.Render("~/bundles/bootstrap-table")
}
So the javascript function ("#btnsearch").click gets the json data from public virtual JsonResult Search and sends that to bootstrapTable which loads the data in the table. What I want to do is to add a new header in my table, like this:
<table id="table" class="table">
<thead>
<tr>
<th data-field="MyDataNumber" data-sortable="true">Number</th>
<th data-field="MyDataCreatedate" data-sortable="true">Created</th>
<th data-field="Status" data-sortable="true">Status</th>
<th></th>
</tr>
</thead>
</table>
And then in the last column add a delete button that has the id of that row (#Model.Id for instance) so that I can call the controller to delete the row from the database and then reload the table so that the row also disappears from the GUI.
I could easily do it with an ActionLink but since I don't loop through all objects and then draw them out on the page, I can't just add an ActionLink to the page. All the rendering of the rows is done in the bootstrapTable.
I looked at this question and answer and it seemed promising but it's not quite what I'm doing and I can't get my head around what I would need to do to get it working for me: Bootstrap table - dynamic button in row.
According to documantation and examples here:
https://live.bootstrap-table.com/example/column-options/events.html
Add to your scripts:
<script>
var $table = $('#table')
function operateFormatter(value, row, index) {
return [
'<a class="remove" href="javascript:void(0)" title="Remove">',
'<i class="fa fa-trash"></i> Delete',
'</a>'
].join('')
}
window.operateEvents = {
'click .remove': function (e, value, row, index) {
//edit here for ajax request to delete row.id record
$.ajax({
type: "POST",
url: "#Url.Action(MVC.MyController.ActionNames.Delete,MVC.MyController.Name)",
data: {id:row.id},
dataType: "json",
success: function (data) {
//when success remove row
$table.bootstrapTable('remove', {
field: 'id',
values: [row.id]
})
},
error: function (err) {
console.log(err)
}
});
}
}
</script>
and edit your html table:
<table id="table" class="table">
<thead>
<tr>
<th data-field="MyDataNumber" data-sortable="true">Number</th>
<th data-field="MyDataCreatedate" data-sortable="true">Created</th>
<th data-field="Status" data-sortable="true">Status</th>
<th data-field="operate" data-formatter="operateFormatter" data-events="operateEvents">Actions</th> <!--add this col-->
</tr>
</thead>
</table>

Dynamically add Select2 to Row

why when i try to add select2 to new row the new select2 failed to initialize (it shown as select html tag).
Here's my code to create the table :
<table id="tbldet" class="table table-bordered table-striped table-hover" style="width:100%;margin:0 auto;">
<thead>
<tr>
<th><p>Nama Barang</p></th>
<th><p>Harga</p></th>
<th><p>Qty</p></th>
<th><p>Total</p></th>
<th style="width:50px"><p>Aksi</p></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select class="select2" name="det_brg" style="width:100%;">
</select>
</td>
<td>10000</td>
<td>4</td>
<td>930000</td>
<td><span class="btn btn-danger"><i class="fa fa-remove"></i></span></td>
</tr>
</tbody>
</table>
javascript function to initializeSelect :
function initializeSelect2(selectElementObj) {
selectElementObj.select2({
width: "80%",
tags: true,
language:"id",
ajax: {
url: "controller/barang_list.php",
dataType: "json",
type:"GET",
delay: 250,
data: function (params) {
return {
search: params.term
}
},
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
id:item.id,
text:item.text
}
})
};
},
cache: false
},
minimumInputLength: 3,
dropdownParent:$("#form-data")
});
};
$(".select2").each(function() {
initializeSelect2($(this));
});
here's the code to add new row :
//create new row
$("#add_row").click(function(e) {
//new row
$("#tbldet").append(
'<tr>\
<td>\
<select class="select2" name="det_brg" style="width:100%;">\
</select>\
</td>\
<td>10000</td>\
<td>4</td>\
<td>930000</td>\
<td><span class="btn btn-danger"><i class="fa fa-remove"></i></span></td>\
</tr>'
);
var newSelect=$(this).closest("tr").find(".select2");
initializeSelect2(newSelect);
})
i suspect there's problem with finding new 'select2' component on new row, but when i use alert(newSelect) it didn't show NULL / Undefined
Your suspicion is correct, your code will never find the new .select2 element. The reason has to do with the way .closest() works. You can investigate that here:
https://api.jquery.com/closest/
But in the mean time:
Change
var newSelect=$(this).closest("tr").find(".select2");
TO
var newSelect=$("#tbldet").find(".select2").last();

Table disappears after adding an item

i'm using datatables to display a list of project names and I'm using a button to add an item to the displayed array, but when i do so, my table disappears.
Here's the code:
view.html
<button ng-click="vm.add()">Add item</button>
<table datatable="ng" dt-instance="vm.dtInstance" dt-options="vm.dtOptions" dt-column-defs="vm.dtColumnDefs"
class="table table-hover table-striped table-bordered table-condensed">
<thead>
<tr style="background-color: #00b3ee; color: white; border:none">
<th style="text-align: center">Nom</th>
<th style="text-align: center">Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="project in vm.project.projects">
<td style="width: 90%; vertical-align: middle">{{project}}</td>
<td align="center" style="vertical-align: middle">
<button data-toggle="modal" ng-click="vm.setProject(project)"
data-target="#deleteEureciaProjectModal" type="button" class="btn btn-danger">
<i class="fa fa-trash"> </i>Supprimer
</button>
</td>
</tr>
</tbody>
</table>
controller.js
vm.add = () => vm.project.projects.push('new project');
fetchProject().then(result => {
vm.project = result;
// vm.project = {
// projects: [
// "project1",
// "project2",
// "project3",
// "project4"
// ],
// etc...
// }
vm.project.projects.push("newProject"); //it's working here, which is normal
//init datatable
vm.dtInstance = {};
vm.dtOptions = DTOptionsBuilder.newOptions()
.withBootstrap();
vm.dtColumnDefs = [];
for (var i = 0; i < 2; i++) {
if (i == 1) {
vm.dtColumnDefs.push(DTColumnDefBuilder.newColumnDef(i).notSortable());
} else {
vm.dtColumnDefs.push(DTColumnDefBuilder.newColumnDef(i));
}
}
})
I've tried using objects instead of strings.. doesn't work either. I don't know what's going on.
I cannot use server side processing. This has to be done using the angular way.
Ok, so i found it :
For some reason, it worked when i initialized vm.project.project before the promise call. So i created the vm.project object, and i added the project property to it by adding an empty array. I was then able to add items without having my table disappearing.

How to populate table based on button click

I have a table which contains some data about car makes.
It looks like this:
Now in the table appears data for all makes, but I need to show data only for the make that I've clicked. For example if I click on Audi to show data only for this make.
This is my view where I have populated the table:
<div class="row">
#{var testList = Model.ProductMatchingVehicles.GroupBy(p => p.Make.Name).ToList(); foreach (var item in testList) {
<div class="btn btn-danger btnMake" data-id="#item.Key" id=btnMake onclick="myFunction()">#item.Key</div>
} }
</div>
<div class="row">
<div class="col-xs-12">
<table class="table table-condensed table-striped table-bordered">
<thead>
<tr>
<th>Make</th>
<th>Model</th>
<th>Engine</th>
<th>Data</th>
<th></th>
</tr>
</thead>
<tbody>
#if (Model.ProductMatchingVehicles != null) { foreach (var item in Model.ProductMatchingVehicles) {
<tr>
<td>#item.Make.Name</td>
<td>#item.Model.Name</td>
<td>#item.Engine.Name</td>
</tr>
} }
</tbody>
</table>
</div>
</div>
Can you please advise me how to achieve this in javascript or jquery? Thanks!
You can try with following code:
1) Modify <tbody> as follows:
<tbody>
#if (Model.ProductMatchingVehicles != null) { foreach (var item in Model.ProductMatchingVehicles) {
<tr class="vehicle_rows" data-refId="#item.Key">
<td>#item.Make.Name</td>
<td>#item.Model.Name</td>
<td>#item.Engine.Name</td>
</tr>
} }
</tbody>
Here we have added the class and data-refId attribute to each <tr>
2) Modify the button click function a bit:
<div class="btn btn-danger btnMake" data-id="#item.Key" id=btnMake onclick="myFunction(this)">#item.Key</div>
Here passing this reference to function
3) The function myFunction will have logic something like this:
function myFunction(obj){
var $button = $(obj);
var car_make = $button.data("id"); //reading the data-id of clicked button
//hide all rows first
$(".vehicle_rows").hide();
//show only currenly clicked buttons associated rows
$(".vehicle_rows[data-refId="+car_make+"]").show();
}

how to insert only unique value in Editor templates in mvc

i want to enter only unique Machine_serial_no in my editor templates , user can add Machine_serial_no through browsing a file or can enter manually As shown in below code, i just want to make sure that user shouldnot allow to enter same value twice .your suggestion is always welcome
..Thanks in advance..
//main view
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery-ui-1.9.2.min.js"></script>
<div id="cast">
<tr>
<td> File:</td>
<td><input type="file" id="file" /> </td>
<td> <input type="button" value="Upload" id="btnSubmit" /> </td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="manualSerial">
<td class="required">Total No of serial no U want to enter:</td>
<td>#Html.TextBoxFor(x => x.count, new { #Value = 0 })</td>
<td colspan="4">
<input type="button" value="Add Serial" id="addserial" />
#*#Html.ActionLink("Add Serial", "AddMachineSerial", "Import", new { #id = "addserial" ,})
#Html.ValidationMessageFor(model => model.serials.Machine_serial_no)*#
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td id="ShowModel" colspan="6">
<table id="tbl1" style="width:100%;">
<thead>
<tr>
<td>Brand</td>
<td>Machine</td>
<td>Model</td>
<td>Serial No</td>
<td>Mac Address</td>
<td>Action</td>
</tr>
</thead>
</table>
</td>
</tr>
<tr>
<td id="ShowModel" colspan="6">
<div style="height:253px; width:100% ;overflow: auto;">
<table style="width:100%;margin-left:0px;margin-right:0px">
#*<thead>
<tr>
<th style="width:45px;">Brand</th>
<th style="width:90px;">Machine</th>
<th style="width:80px;">Model</th>
<th>Serial No</th>
<th>Mac Address</th>
<th>Action</th>
</tr>
</thead>*#
<tr>
<td colspan="6" id="td_serial"></td>
</tr>
</table>
</div>
</td>
</tr>
//jquery
$('#addserial').click(function () {
var count = $('#count').val();
var i;
if ($('#searchid').val() != '') {
if ($('#count').val() != 0) {
for (i = 0; i < count; i++) {
$.ajax({
type: 'GET',
data: { mid: $('#machineTypes_MTId').val(), modelName: $('#searchid').val(), modelId: $('#searchValue').val() },
url: '#Url.Action("AddMachineSerial","Import")',
success: function (response) {
$('#ShowModel').show();
$('#td_serial').prepend(response);
$('#count').val(0);
}
});
}
}
else {
alert("Enter no of serial you want to enter!")
}
}
else {
alert("select Model First!")
$('#count').val(0);
}
});
//editor Templates /parital view
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#using (Html.BeginCollectionItem("serialList"))
{
#Html.ValidationSummary(true)
<div id="DeleteTxt1">
<table id="tbl1" style="width:100%;margin-left:0px;margin-right:0px">
<tr class="importitem1">
<td>#Model.brandName</td>
<td>#Model.machineName</td>
<td>#Model.MachineModel</td>
#*<td class="required">Machine Serial No.:</td>*#
<td>
#Html.TextBoxFor(x => x.Machine_serial_no, new { placeHolder = "Enter Machine Serial here.", #class = "serial1"})
#Html.ValidationMessageFor(x => x.Machine_serial_no)
</td>
<td><input type="button" value="Cancel" id="DeleteBtn1" style="color:red;" /></td>
</tr>
</table>
</div>
}
Assuming you want to alert the user as soon as they enter a non unique value, then you need to handle the .change() event of the textbox, and since the textboxes are being added dynamically, you need to use event delegation
$('#td_serial').on('change', '.serial1', function() {
var isvalid = true;
var inputs = $('.serial1').not($(this));
var text = $(this).val();
$.each(inputs, function(index, item) {
if ($(this).val() && $(this).val() === text) {
isvalid = false;
return false;
}
});
if (!isvalid) {
alert('not unique!');
}
});
Note the alert('not unique!') is just for testing purposes - its not clear how you want to notify the user - e.g. include a div with an error message that your might show/hide as required
Next your partial includes #Html.ValidationMessageFor(x => x.Machine_serial_no) suggesting you have validation attributes. In order to get client side validation for dynamically created elements you need to re-parse the validator when the new elements have been added. Modify your script to
for (i = 0; i < count; i++) {
$.ajax({
type: 'GET',
data: { mid: $('#machineTypes_MTId').val(), modelName: $('#searchid').val(), modelId: $('#searchValue').val() },
url: '#Url.Action("AddMachineSerial","Import")',
success: function (response) {
$('#ShowModel').show();
$('#td_serial').prepend(response);
$('#count').val(0);
// Reparse the validator
$('form').data('validator', null);
$.validator.unobtrusive.parse(form);
}
});
}
Side note - consider modifying this so that you only re-parse once all ajax calls are complete
Note also that you should only have one #Html.ValidationSummary(true) (your currently is adding one for each partial) and you need to remove the scripts from the partial - your should have one copy of the scripts only in the main view
I think this is you want to validate client side
$(function (){
$('#partialViewtextbox_Id').change(function (){
var partial = $('#partialViewtextbox_Id').val();
var main = $('#maintextbox_Id').val();
if(partial == main)
{
alert("value already available");
}
});
});

Categories