How to get a variable in a modal using datatable in laravel? - javascript

I am using yajra datatables in laravel and I have the "revisar" button that shows a modal (as shown in the following image):
modal show
I want to fill this textarea with information from the "detail" field of the database that is obviously different for each item of the datatable, how would you do to obtain that data? I thought about getting it from the variable of the partials.actions which I can send from the controller of the datatable, but I can't get that variable in blade view.
my partials.actios view:
<a href="{{ route('tareas.createfrom', Hashids::encode($id)) }}" class="btn btn-sm btn-success">
<i class="fas fa-fw fa-plus"></i>
Tarea
</a>
<a href="{{ route('solicituds.show', Hashids::encode($id)) }}" class="btn btn-sm btn-info">
<i class="fas fa-fw fa-eye"></i>
Ver
</a>
<button type="button" data-id="{{ $id }}" data-toggle="modal" data-target="#RevisaSolicitudModal" class="btn btn-warning btn-sm revisar" id="getActualizaId">
<i class="fas fa-fw fa-check-circle"></i>
Revisar
</button>
<button type="button" data-id="{{ $id }}" data-toggle="modal" data-target="#DeleteProductModal" class="btn btn-danger btn-sm" id="getDeleteId">
<i class="fas fa-fw fa-trash"></i>
Eliminar
</button>
Maybe I can get the variable "$detail" in the modal using JS, I don't know

Check bootstrap documentation: https://getbootstrap.com/docs/4.4/components/modal/#varying-modal-content
<button type="button" data-id="{{ $id }}" data-toggle="modal" data-target="#RevisaSolicitudModal" class="btn btn-warning btn-sm revisar" id="getActualizaId">
<i class="fas fa-fw fa-check-circle"></i>
Revisar
</button>
...
<script>
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget) // Button that triggered the modal
var id = button.data('id') // Extract info from data-* attributes
...
})
</script>

My Approach which worked:
1.Controller:
return \Yajra\DataTables\DataTables::of($trxDatatables)
->addIndexColumn()
->addColumn('action', function($row){
$stEditRoute = route('admission.students.edit',$row->id);
$stShowRoute = route('admission.students.show',$row->id);
$btns = '<button class="btn btn-danger btn-xs
deleteModalTriggerBtn " id="deleteModalTriggerBtn"
data-catid='.$row->id.' data-toggle="modal"
data-target="#delete"><span class="glyphicon glyphicon-trash" title="Delete Center"/></button>';
return $btns;
})
->rawColumns(['action'])
->toJson();
Jquery:
$(document).ready(function () {
// used the following technique so that I can use the custom attribute (data-catid) value of the trigger button (id="delete") when delete ajax is called.
$(function() {
var stId = null;
function getCatId() {
$('#delete').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget) // Button that triggered the modal
var id = button.data('catid'); // Extract info from data-* attributes
stId = id;
});
}
getCatId();
$('.modal-footer').on('click', '.delete', function(e) {
e.preventDefault();
var token = $("meta[name='csrf-token']").attr("content");
var reason = $("#reason option:selected").text();
var notice = $("#notice").val();
$.ajax({
type: 'DELETE',
url: 'http://yoursite.test/workplace/admission/students/'+stId,
data: {
'id': stId,
'reason': reason,
'notice': notice,
"_token": token,
},
success: function (data) {
// console.log(data);
// $('.item' + $('.id').text()).remove();
}
});
});
});
});

Related

Bootstrap Modal inside a table populated from a partial

This is follow up question on this (Bootstrap Modal Confirmation using ASP.Net MVC and a table)
Using MVC .NetCore, I populate a "partial" view and a Table (called _Match_StatsViewAll.cshtml under a directory of the same name of my controller Match_Stats).
It's being called from an Indexview:
public async Task<ViewResult> Match_StatsIndex(string message, string comp_id, string match_id, string team_id)//ACTION METHOD/View Results
Within that table (code below) , a list of records. Each row have a button to edit or delete. To delete a record, I need to have 4 IDs since the PK is made of those 4 keys. I was able to make it work with a javascript, however, I did not like the "confirm" display being produced. Thanks to this post, I was able to add a modal for each rows in the table and delete the record. However now, If I use the original json call to refresh the partial model (that only refresh the table), I have this screen:
Here is a Row being populated from my Model:
<td>
<div>
#{i++; }
<a onclick="showInPopup('#Url.Action("Match_StatsCreateOrEdit","Match_Stats",new {comp_id=item.Match_Stats.Comp_Id, team_id=item.Match_Stats.Team_Id,match_id=item.Match_Stats.Match_Id, match_Stat_Id=item.Match_Stats.Match_Stat_Id},Context.Request.Scheme)','Update A Stat')" class="btn btn-primary btn-xs"><i class="fas fa-pencil-alt"></i> Edit</a>
<form asp-action="Match_StatsDelete" asp-route-comp_Id="#item.Match_Stats.Comp_Id" asp-route-team_Id="#item.Match_Stats.Team_Id" asp-route-Match_Id="#item.Match_Stats.Match_Id"
asp-route-Match_Stat_Id="#item.Match_Stats.Match_Stat_Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete</button>
</form>
#*//add the button to launch the modal*#
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal-removeplayers_#i"><i class="fas fa-trash"></i> Delete modal</button>
<div class="modal fade" id="modal-removeplayers_#i">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Confirmation needed</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Do you really want to delete this record ?</p>
</div>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<form asp-action="Match_StatsDelete" asp-route-comp_Id="#item.Match_Stats.Comp_Id" asp-route-team_Id="#item.Match_Stats.Team_Id" asp-route-Match_Id="#item.Match_Stats.Match_Id"
asp-route-Match_Stat_Id="#item.Match_Stats.Match_Stat_Id" onsubmit="return jQueryAjaxDeleteDirect(this)" class="d-inline">
<button type="submit" class="btn btn-warning btn-xs"><i class="fas fa-trash"></i> Delete Json</button>
</form>
</div>
</div>
</div>
</div>
</div>
</td>
In my controller - calling the delete :
public async Task<IActionResult> Match_StatsDelete(string comp_id, string team_id, string match_id, string match_stat_id)
{
// Wrap the code in a try/catch block
try
{
var deleteok = _match_statsRepository.Delete(entity);
if (deleteok != null)
{
//Code Here to populate my table only since this is a partial view inside a page
return Json(new { isValid = true, html = JavaScriptConvert.RenderRazorViewToString(this, "_Match_StatsViewAll", myPartialmodelpopulated) });
}
else
{
ModelState.AddModelError("", "Could not Delete Match");
return RedirectToAction("MatchIndex", new { message = "Success", comp_id });
}
}
catch (Exception ex)
{
// Log the exception to a file.We discussed logging to a file
//......More code here for the log has been removed //
return View("Error");
}
}
Here is the Javascript:
jQueryAjaxDeleteDirect = form => {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
$('#view-all').html(res.html);
$.notify('Deleted Successfully !', {
globalPostion: 'Top Center',
className: 'success'
});
},
error: function (err) {
console.log(err)
}
})
} catch (ex) {
console.log(ex)
}
//prevent default form submit event
return false;
}
The " return Json" call works fine if I use the original code (so no MODAL form - just the javascript "confirm") .
Thank you for the help!

use laravel query with DataTable

I tried to initialise a DataTable with data which comes from a database via this query:
public function qryUsers()
{
$users = User::orderBy('name')
->get();
return $users;
}
javascript:
function loadTable() {
$.getJSON('/admin/users3/qryUsers')
.done(function (data) {
console.log('data', data);
$('#table_id').DataTable({
"ajax": data,
"columns": [
{"data": "id"},
{"data": "name"},
{"data": "email"},
{"data": "active"},
{"data": "admin"}
]
});
})
.fail(function (e) {
console.log('error', e);
});
};
When I execute this, I get the error: DataTables warning: table id=table_id - Invalid JSON response.
When I check my json response in F12 -> network with jsonlint it says that this is valid json, so I don't really know what I'm doing wrong here.
This is what I've tried before, but when I add or delete or update a user, something goes wrong with reloading the table, which I do after each delete, add or update function. It just gives me all users, where it should give 10 with pagination, and when I sort them it still seems to use old data.
$.getJSON('/admin/users3/qryUsers')
.done(function (data) {
console.log('data', data);
// Clear tbody tag
$('tbody').empty();
// Loop over each item in the array
$.each(data, function (key, value) {
let tr = '';
if (value.name === "Amber Akkermans") {
tr = `<tr>
<td>${value.id}</td>
<td>${value.name}</td>
<td>${value.email}</td>
<td>${value.active}</td>
<td>${value.admin}</td>
<td>
<form action="/admin/users3/${value.id}" method="post" class="deleteForm">
#method('delete')
#csrf
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-success btn-edit"
data-toggle="tooltip"
data-user="${value.name}"
data-id="${value.id}"
data-email="${value.email}"
data-active="${value.active}"
data-admin="${value.admin}"
title="Edit ${value.name}" disabled>
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-outline-danger btn-delete"
data-toggle="tooltip"
data-user="${value.name}"
data-id="${value.id}"
title="Delete ${value.name}" disabled>
<i class="fas fa-trash-alt"></i>
</button>
</div>
</form>
</td>
</tr>`;
} else {
tr = `<tr>
<td>${value.id}</td>
<td>${value.name}</td>
<td>${value.email}</td>
<td>${value.active}</td>
<td>${value.admin}</td>
<td>
<form action="/admin/users3/${value.id}" method="post" class="deleteForm">
#method('delete')
#csrf
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-success btn-edit"
data-toggle="tooltip"
data-user="${value.name}"
data-id="${value.id}"
data-email="${value.email}"
data-active="${value.active}"
data-admin="${value.admin}"
title="Edit ${value.name}">
<i class="fas fa-edit"></i>
</button>
<button type="button" class="btn btn-outline-danger btn-delete"
data-toggle="tooltip"
data-user="${value.name}"
data-id="${value.id}"
title="Delete ${value.name}">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</form>
</td>
</tr>`;
}
$('tbody').append(tr);
});
$('#table_id').DataTable();
})
.fail(function (e) {
console.log('error', e);
})
}
All help is appreciated!
to return information to the format json.
change qryUsers function to :
public function qryUsers()
{
$users = User::orderBy('name')
->get();
return response()->json($users);
}

edit state in vue js inside v-for

I'm fetching comments from api. and I'm trying to edit a comment from the list.
When i click edit i show a text area inside the comment box and a button to save the comment . which is working nicely.
The problem is when i click edit the edit textarea gets applied to all comment boxes :|
<div>
<i class="fas fa-pen text-action text-success mr-3" #click="showComment(comment.id)" v-if="user == comment.user_id" v-b-tooltip.hover title="edit"></i>
<i class="fas fa-times-circle text-danger" v-b-tooltip.hover title="delete" v-if="!editing" v-show="user == comment.user_id"></i>
<i class="fa fa-times text-action text-danger mr-3" v-if="editing" #click="editing = false" v-b-tooltip.hover title="cancel editing"></i>
</div>
</div>
<div v-if="editing">
<textarea class="form-control" v-model="commentEdited" :id="comment.id" :placeholder="comment.body"></textarea>
<button class="btn btn-xs btn-success" #click="editComment(comment)">save</button>
</div>
The show comment method :
showComment(comment_id) {
console.log("clicked" + comment_id);
for (let i = 0; i < this.comments.length; i++) {
if (this.comments[i].id == comment_id) {
this.comment.body = this.comments[i].body;
this.comment.id = this.comments[i].id;
this.editing = true;
}
}
},
the editing is a boolen.
when i click edit it should only open the textarea for the current comment only . not all the comments :\
I really cant figure this out .Any help is appreciated .
Its because editing boolean is used by all of the components so when setting it to true, all comments show. You could change editing to a string property that is equal to the id of the comment being edited:
<div>
<i class="fas fa-pen text-action text-success mr-3" #click="showComment(comment.id)" v-if="user == comment.user_id" v-b-tooltip.hover title="edit"></i>
<i class="fas fa-times-circle text-danger" v-b-tooltip.hover title="delete" v-if="!editing" v-show="user == comment.user_id"></i>
<i class="fa fa-times text-action text-danger mr-3" v-if="editing" #click="editing = ''" v-b-tooltip.hover title="cancel editing"></i>
</div>
<div v-if="editing == comment.id">
</div>
showComment(id) {
this.editing = id
},
the reason is you are having editing as a common variable, i suggest you instead to carry a variable that holds the 'id'of your clicked comment, so
if you have something like
<div v-if="commentId===comment.id">
<textarea class="form-control" v-model="commentEdited" :id="comment.id" :placeholder="comment.body"></textarea>
<button class="btn btn-xs btn-success" #click="editComment(comment)">save</button>
</div>
where commentId is the variable into which you store the selected comment.id after that make it '' empty...
this would be my approach

jQuery submit form normally or Ajax dependant on variable using FontAwesome buttons

I am using buttons for submit, as that is the only easy way to use fontawesome buttons. I detect which button was selected and place that value in a hidden field so that it is available in my Ajax routine.
This presents a problem, as one button requires a normal submit, as it goes to a script that creates a pdf.
The other conditions submit using Ajax. I attempted the following which, of course, will not work, as it creates a recursion loop.
Cannot figure a means to do this without creating a submit loop.
In Form:
<input type="hidden" id="Clicked" name="Clicked" value="" />
<button type="submit" class="btn btn-success ClickCheck" id="Create" style="display:inline;"> <i class="fa fa-file-pdf-o"> <span>Create Bill</span></i></button>
<button type="submit" class="btn btn-success ClickCheck" id="Reset" style="display:inline;"> <i class="fa fa-times"> <span>Reset</span></i></button>
<button type="submit" class="btn btn-success ClickCheck" id="SaveData"> <i class="fa fa-archive"> <span>Save Only</span></i></button>
<button type="submit" class="btn btn-success ClickCheck" id="Create-Save"> <i class="fa fa-archive"> <span>Create and Save</span></i></button>
jQuery Code:
$(document).ready(function()
{
$('.ClickCheck').click(function()
{
var ButtonID = $(this).attr('id');
$('#Clicked').val(ButtonID);
});
$("#MyForm").on("submit", function(event)
{
event.preventDefault();
var Form = $('#MyForm');
var Valid = verify();
if(Valid)
{
if($('#Clicked').val() == "Create")
{
$(Form).attr('action', './blformpdf.php');
$(Form).submit();
}
else
{
$.ajax(
{
type: "POST",
url: "scripts/Ajax.php",
data: Form.serialize(),
success: function(response)
{
console.log(response);
}
});
}
}
});
});
The callback should be done from verify() , I've written an example .
var goIsWaiting=false;
var goIsActive=false;
function go(){
if(goIsActive)
adviseGoIsActive()
else{
console.log("Go Is Waiting !");
goIsWaiting=true;
}
}
function activate(){
//.. Doing some stuff here
if(goIsWaiting) adviseGoIsActive();
goIsActive=true;
}
function adviseGoIsActive(){
console.log("Go Is Active !")
}
<input type="submit" value="Go" onClick="go()">
<input type="submit" value="Activate Go Action" onClick="activate()">
The solution for this problem was simply to use links rather than <input> or <button>.
Here is the HTML:
<input type="hidden" id="Clicked" name="Clicked" value="" />
<a class="btn btn-success ClickCheck" id="Create" href="javascript:void(0)"> <i class="fa fa-file-pdf-o"> <span>Create Bill</span></i></a>
<a class="btn btn-success ClickCheck" id="Reset" href="javascript:void(0)"> <i class="fa fa-times"> <span>Reset</span></i></a>
<a class="btn btn-success ClickCheck" id="SaveData" href="javascript:void(0)"> <i class="fa fa-archive"> <span>Save Only</span></i></a>
<a class="btn btn-success ClickCheck" id="Create-Save" href="javascript:void(0)"> <i class="fa fa-archive"> <span>Create and Save</span></i></a>
One of these buttons is a reset. Although you can define a <button> as type="reset", for consistency, as well as other reasons, I left that too as a link and, since the button id is part of my post, the Ajax script detects that and just returns a null, then used a jQuery reset to clear the form after the null Ajax call.
$(document).ready(function()
{
$('.ClickCheck').click(function()
{
var ButtonID = $(this).attr('id');
$('#Clicked').val(ButtonID);
var Form = $('#MyForm');
var Valid = verify(); // form verify function
if(Valid)
{
if(ButtonID == "Create") // Send to PDF script
{
$(Form).attr('action', './blformpdf.php');
$(Form).submit();
}
else
{
$.ajax(
{
type: "POST",
url: "scripts/Ajax.php",
data: Form.serialize(),
success: function(response)
{
// Do whatever here with response data
}
}
if(ButtonID == "Reset")
{
$('#MyForm').trigger("reset");
$('#Clicked').val('');
}
}
}
});
});

How to send a collection of Models to the MVC controller or view using javascript/jQuery

I have a controller which gets a Model as parameter, but the Model has a collection of another Model. The other parameters can be simply sent using a Form but the inputfield of the model are dynamic so you can add them using javascript or jQuery.
So what I don't know is, how to make a collection of the models from the inputs using javascript and send them to the controller.
this is what I have in the View
<div>
<div class="row">
<div class="col-xs-4 col-sm-6 ">
<div class="dropdown volledigeLengte verplicht-ruimte">
<button class="form-control btn btn-default dropdown-toggle #dis" data-toggle="dropdown">
verplichte velden toevoegen<i class="glyphicon glyphicon-chevron-down"></i>
</button>
<ul class="dropdown-menu volledigeLengte">
<li>Text <i class="glyphicon glyphicon-plus "></i>
<li>Foto <i class="glyphicon glyphicon-plus "></i>
<li>Kaart <i class="glyphicon glyphicon-plus "></i>
<li>Video <i class="glyphicon glyphicon-plus "></i>
</ul>
</div>
<div class="marging-top-voor-fields extraRuimtesVerplicht">
</div>
</div>
<div class="col-xs-4 col-sm-6 ">
<div class="dropdown volledigeLengte niet-verplicht-ruimte">
<button class="form-control btn btn-default dropdown-toggle #dis" data-toggle="dropdown">
Niet verplichte velden toevoegen <i class="glyphicon glyphicon-chevron-down"></i>
</button>
<ul class="dropdown-menu volledigeLengte">
<li>Text <i class="glyphicon glyphicon-plus "></i>
<li>Foto <i class="glyphicon glyphicon-plus "></i>
<li>Kaart <i class="glyphicon glyphicon-plus "></i>
<li>Video <i class="glyphicon glyphicon-plus "></i>
</ul>
</div>
<div class="extraRuimtesNietVerplicht marging-top-voor-fields">
</div>
</div>
</div>
</div>
this is what my javascript looks like
(function ($) {
$(function () {
var aantalVerplicht = 0;
var aantalNietVerplicht = 0;
var matrix = [];
for (var i = 0; i < 9; i++) {
matrix[i] = [];
for (var j = 0; j < 9; j++) {
matrix[j] = new Array(9);
}
}
var extra;
var addRuimte = function (e, type) {
extra = null;
if ($(this).parents('div').hasClass("verplicht-ruimte")) {
extra = $(".extraRuimtesVerplicht");
}
if ($(this).parents('div').hasClass("niet-verplicht-ruimte")) {
extra = $(".extraRuimtesNietVerplicht");
}
if (extra != null) {
$(extra).append('<div id="maring-top-voor-fields"><input class="col-sm-10 form-control" placeholder="Geef de vraag" /><span class="input-group-btn remove_ruimte"><button class ="col-sm-2 form-control btn btn-danger "><i class="glyphicon glyphicon-minus"></i></button></span></div>');
}
};
var removeRuimte = function (e) {
e.preventDefault();
$(this).parent('div').remove();
i--;
};
$(document).on('click', '.text', addRuimte("text"));
$(document).on('click', '.foto', addRuimte("foto"));
$(document).on('click', '.kaart', addRuimte("kaart"));
$(document).on('click', '.video', addRuimte("video"));
$('.extraRuimtesVerplicht').on('click', '.remove_ruimte', removeRuimte);
$('.extraRuimtesNietVerplicht').on('click', '.remove_ruimte', removeRuimte);
});
})(jQuery);
this is what it looks like
I resolved a similar problem as follows.
Ensure that all IDs are unique
Use form tags
The following JavaScript then sends the form content to the server (I have generalised this to include to forms - the original worked with 10 forms).
function SaveAllAsIs() {
// save section 5 summaries first
var form_section11Data = JSON.stringify($("#form_section11").formParams());
var form_section11Data = JSON.stringify($("#form_section12").formParams());
$.ajax({
type: 'POST',
url: '/Area/DataSave/SaveAsIs',
data: JSON.stringify({
form_section11: form_section11Data,
form_section12: form_section12Data
}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data.Success == "False") { alert("Error saving data, please try later"); }
}
});
}
The controller method looks like:
public JsonResult SaveAsIs(string form_section11, string form_section12)
{
SerializeModel(new JavaScriptSerializer().Deserialize<IDictionary<string, object>>
(form_section11, targetModel1);
SerializeModel(new JavaScriptSerializer().Deserialize<IDictionary<string, object>>
(form_section12, targetModel2);
}
And finally
public static void SerializePerinatalModel<T>(IDictionary<string, object> dataModel, T perinatalModel, int perinatalReportID)
{
Type sourceType = typeof(T);
foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
{
if (dataModel.ContainsKey(propInfo.Name))
I have only shown a partial function, but essentially each type is checked to see if it a list, and is so the list is then converted.
The other parameters can be simply sent using a Form but the inputfield of the model are dynamic so you can add them using javascript or jQuery.
Scott Hanselman has some details on passing arrays to MVC control binding: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
Which is essentially: ensure your controls have the correct names: using an index for lists
Although this doesn't directly address dynamic fields, it shows how it can be done.
replace:
$(extra).append('<div id="maring-top-voor-fields"><input class="col-sm-10 form-control" placeholder="Geef de vraag" /><span class="input-group-btn remove_ruimte"><button class ="col-sm-2 form-control btn btn-danger "><i class="glyphicon glyphicon-minus"></i></button></span></div>');
with:
var count = $("div#maring-top-voor-fields>input.col-sm-10.form-control").length;
$(extra).append(' ... <input name="answer["+ count + 1+"]" class="col-sm-10 form-control" placeholder="Geef de vraag" /> ... ');
One caveat: there cannot be any gaps in the numbers - so if you also dynamically remove any controls, then you'll have to change all the names to re-index them (which isn't very nice tbh).
With this, you can keep your controllers neat with IList<whatever> and have the framework bind them for you.
Alternatively, just use jquery!

Categories