I created an ajax request to display results from my table eloquent query who depends one a select box "poule".
Everything is working but when I run the ajax request by selecting a poule_id from the select box I need to display the json result. I would like to display the result as my foreach loop in the table ($equipes as $equipe) because as you can see I display value from models in relation.
UPDATED:
My model Equipe:
class Equipe extends Model
{
public function structure()
{
return $this->belongsTo('App\Structure');
}
My model CompetEquipe (i use it to display my foreach)
class CompetEquipe extends Model
{
public function equipe(){
return $this->belongsTo('App\Equipe' , 'equipe_id');
}
Like this i can access to the tables in relations in my foreach
<tr>
<td>
{{$equipe->equipe->structure->nom_structure}}
</td>
<td>
{{$equipe->equipe->lb_equipe}}
</td>
<td>{!! Form::text('nb_bonus') !!}</td>
</tr>
Actually with this way I can only display equipe_id but I would like to display the object to access to the other models in relation and display the result as my foreach in the table like:
#foreach($equipes as $equipe)
<tr>
<td>
{{$equipe->equipe->structure->nom_structure}}
</td>
<td>
{{$equipe->equipe->lb_equipe}}
</td>
<td>{!! Form::text('nb_bonus') !!}</td>
</tr>
#endforeach
Hope someone understood what I want to do. thanks a lot in advance friends
here my JSON RESULT : {"equipes":[{"equipe_id":1,"poule_id":1}]}
My select filter search:
<select id="poule">
#foreach($select_poules as $select_poule)
<option value="{{$select_poule->id}}">{{$select_poule->lb_poule}}</option>
#endforeach
</select>
My table:
<table id="equipes" class="table table-striped">
<thead>
<tr>
<th>Club</th>
<th>Nom de l'équipe</th>
<th>Bonus(+/-)</th>
</tr>
</thead>
<tbody>
#foreach($equipes as $equipe)
<tr>
<td>
{{$equipe->equipe->structure->nom_structure}}
</td>
<td>
{{$equipe->equipe->lb_equipe}}
</td>
<td>{!! Form::text('nb_bonus') !!}</td>
</tr>
#endforeach
</tbody>
</table>
My controller:
public function searchEquipes(Request $request)
{
$equipes = [];
if($request->has('poule_id')){
$equipes = EquipePoule::where('poule_id',$request->poule_id)
->get();
}
return response()->json(['equipes' => $equipes]);
}
My script:
<script>
$(document).on('change', '#poule', function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: 'GET',
dataType: "json",
url : '/licences/public/search/equipes',
data : {
poule_id : $('#poule').val()
},
success:function(data){
$('#equipes').empty();
for (var i = 0; i < data.equipes.length; i++) {
$('#equipes').append('<tr><td>'+data.equipes[i].equipe_id+'</td></tr>')
}
},
timeout:10000
});
});
</script>
To replace the content of your table with the response of an AJAX request you jQuery's replaceWith.
You need to change your jQuery success function slightly.
success: function(data) {
//Build the row data as you wish to display it
var rowData = ""
$.each(team["equipes"][0], function(i, value) {
var rowData += $("#equipes").append("<td>"+value+"</td>");
})
$("#equipes").replaceWith("<tr>"+rowData+"</tr>
$("#equipes").append("</tr>");
}
This will replace your initial table data with that of your select.
Related
I'm trying to send values obtained from datable to a php file but sends null
and return empty values from php
This is what'ive tried
document.addEventListener("DOMContentLoaded", function(event) {
const allButtons = document.querySelectorAll('#tablaUnidades td button');
allButtons.forEach(function(elem) {
elem.addEventListener("click", (e)=> {
e.preventDefault();
var allCells = elem.parentNode.parentNode.cells;
codigo = allCells[0].textContent;
deslar = allCells[1].textContent;
descor = allCells[2].textContent;
opcion = allCells[3].textContent;
console.log(codigo,deslar,descor,opcion);
fetch('bd/crud_unidades.php',{
method: "POST",
data: {codigo, deslar, descor, opcion}
})
.then(res=>res.text())
.then(data=>{
console.log(data);
})
});
});
});
<table class="table table-bordered" id="tablaUnidades" width="100%" cellspacing="0" method="post">
<thead>
<tr>
<th>CODIGO</th>
<th>DESCRIPCIÓN LARGA</th>
<th>DESCRIPCIÓN CORTA</th>
<th>ACCIÓN</th>
</tr>
</thead>
<tbody>
<tr>
<td id="codigo"> value 1</td>
<td id="deslar"> value 2</td>
<td id="descor">value 3</td>
<td><button class='btn btn-primary btnVER' id="VER" name="VER"> Click Me</button></a></td>
</tr>
<?php
}
?>
</tbody>
</table>
crud_unidades.php :
<?php
$codigo = var_dump($_POST['codigo']);
$deslar = var_dump($_POST['deslar']);
$descor = var_dump($_POST['descor']);
$opcion = var_dump($_POST['opcion']);
echo var_dump($codigo);
?>
Now I have no idea on how to assign that javascript variable to the php one to use the phpvariable to look up stuff in my database
please help
The source of your woes is the way you're forming your POST object. You're not assigning key/value pairs, you're just creating an object with values - which is not a valid object and I'll best javascript is throwing an error on that.
Your fetch should look more like this:
fetch('bd/crud_unidades.php',{
method: "POST",
data: {codigo: codigo, deslar: deslar, descor: descor, opcion: opcion}
})
Along those lines, if you update your table cell html in the future, this line might stop working:
var allCells = elem.parentNode.parentNode.cells;
Rather, try using closest(selector) which will work it's way up the DOM tree until it finds the selector match, like:
var allCells = elem.closest('tr').querySelectorAll('td');
var formData = new FormData;
var arr = {'codigo': codigo, 'deslar': deslar, 'descor': descor, 'opcion': opcion};
Object.entries(arr).forEach(([key, value]) => {
formData.append(key,value);
});
fetch('bd/crud_unidades.php',{
method: "POST",
cors: "CROS",
body: formData,
})
This was the correct way
I need to show information on a table in 2.cshtml that is on another 1.cshtml page called using #Html.Action("Action","Controller"), depending on the row selected on a table inside of 1.cshtml, the problem is that the information is not being refresh after the view returns.
When you select a row in table (1.cshtml) javascript gives me the value of the cell that i need from that row, after that i do a ajax post to my controller and it access it succesfully then my controller returns the view and access my 2.cshtml with the table, then it runs in my for to display the information, but the problem is that my 2.cshtml never reloads so the rows of my table are never updated.
Code for posting to controller
function submitForm(row) {
var idTool = el('idTool').value = row.cells[0].innerHTML;
var url_ = '../Tools/ToolTable';
jQuery.ajax({
type: "POST",
url: url_,
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ idToolPost:idTool })
});
}
Controller
[HttpPost]
public ActionResult ToolTable(int idToolPost)
{
var entitieTool = new Models.ToolControlEntities2();
List<Models.Tool> t = entitieTool.Tools.ToList();
List<Models.Equip> eqp = entitieTool.Equips.Include(x => x.Equip_Tool).ToList();
List<Models.Equip_Tool> eqpt = entitieTool.Equip_Tool.Include(x => x.Equip).Where(x => x.id_Tool == idToolPost).ToList();
ToolEquip ttteqpceteqptflt = new ToolEquip(eqpt, t, eqp);
ViewBag.SuccessMessage = "The information was succesfuly displayed.";
return View(ttteqpceteqptflt);
}
Table to show result
<table>
<div>
<thead>
<tr>
<th> Tool</th>
<th> Equip</th>
<th> Active</th>
</tr>
</thead>
</div>
<tbody>
#for (int x = 0; x < Model.eqtool_.Count; x++)
{
<tr>
<td style="display: none"><input id="idEquip" name="eq[#x].id_Equip" type="hidden" value="#Model.eqtool_[x].id_Equip" /></td>
<td style="display: none"><input id="idEquip" name="eq[#x].id_Tool" type="hidden" value="#Model.eqtool_[x].id_Tool" /></td>
<td>#Model.eqtool_[x].Tool.Tool_Name</td>
<td>#Model.eqtool_[x].Equip.Equip_Name</td>
<td>#Html.CheckBox("#Model.eqtool_[x].active")</td>
</tr>
}
</tbody>
</table>
After it runs my for the page dosen't show the new information, here is where i think i'm missing a refresh somewhere.
So I resolve my issue I just used the following:
the table was saved on my "texto" variable, and then I just replace the tbody (the information that i need) with the next line
document.getElementById('tooltabletbody').innerHTML = texto;
I have an onclick function which basically just returns sorted data like following:
$(document).ready(function () {
$(".feedbackClick").click(function () {
$.post("/Analyze/GetSortedByFeedback")
.done(function (data) {
var sellers = $('<table />').append(data).find('#tableSellers').html();
$('#tableSellers').html(sellers);
});
});
});
});
And this is how the table looks like that I'm trying to update after the jquery post:
<table id="tableSellers" class="table table-striped jambo_table bulk_action">
<thead>
<tr class="headings">
<th class="column-title"><h4><i class="fa fa-user" style="text-align:center"></i> <span>Username</span></h4> </th>
<th class="column-title"> <h4><span class="glyphicon glyphicon-tasks salesClick" aria-hidden="true"></span></h4></th>
<th class="column-title"><h4><i class="fa fa-star feedbackClick"></i></h4></th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.rezultati)
{
<tr>
<td>#item.StoreName</td>
<td>
<b>
#item.SaleNumber
</b>
</td>
<td><b>#item.Feedback</b></td>
</tr>
}
</tbody>
</table>
The click would basically just fetch the results and update the table in HTMl...
Can someone help me out?
Edit:
This current method doesn't works... I trigger the event but nothing happens... The code in the Action is called properly, but the results aren't displayed...
Edit 2:
This is the content of the data object after .done:
System.Collections.Generic.List`1[WebApplication2.Controllers.ResultItem]
Edit 3:
This is the action:
public List<ResultItem> GetSortedByFeedback()
{
return lista.OrderByDescending(x => x.Feedback).ToList();
}
Edit4 this is the data after the Alexandru's post:
Array[100]
Now I can do:
data[0].Feedback
And this outputs in console:
61259
Please use this:
public JsonResult GetSortedByFeedback()
{
var list=lista.OrderByDescending(x => x.Feedback).ToList();
return Json(list);
}
If your method is GET please use this:
public JsonResult GetSortedByFeedback()
{
var list=lista.OrderByDescending(x => x.Feedback).ToList();
return Json(list,JsonRequestBehavior.AllowGet);
}
Then please use this:
.done(function (data) {
$('#tableSellers tbody').empty();
$.each(data,function(i,item){
var tr='<tr><td>'+item.StoreName+'</td><td><b>'+item.SaleNumber+'</b></td><td><b>'+item.Feedback+'</b></td></tr>';
$('#tableSellers tbody').append(tr);//append the row
});
});
What you are trying to do is actually appending a JSON data to a HTML element which is of course will not work as expected.
Consider using a template engine like jQuery Templates. You will be able to compile a HTML template and use it to render your data whenever you need. For example:
var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";
// Compile the markup as a named template
$.template( "movieTemplate", markup );
$.ajax({
dataType: "jsonp",
url: moviesServiceUrl,
jsonp: "$callback",
success: showMovies
});
// Within the callback, use .tmpl() to render the data.
function showMovies( data ) {
// Render the template with the "movies" data and insert
// the rendered HTML under the 'movieList' element
$.tmpl( "movieTemplate", data )
.appendTo( "#movieList" );
}
TRy something like this:
$(document).ready(function () {
$("body").on("click",".feedbackClick",function() {//delegate the click event
$.get("/Analyze/GetSortedByFeedback",function(data) {
var sellers = $(data).find('#tableSellers').html();//find the table and take the html
$('#tableSellers').html(sellers);//append the html
});
});
});
Note: you need to return html (in your case) from the ajaxed page
from #Alexandru partial response you can do the following
public JsonResult GetSortedByFeedback()
{
var list=lista.OrderByDescending(x => x.Feedback).ToList();
return Json(list,JsonRequestBehavior.AllowGet);
}
js:
$(document).ready(function () {
$("body").on("click",".feedbackClick",function() {//delegate the click event
$.get("/Analyze/GetSortedByFeedback",function(data) {
$('#tableSellers tbody').empty();//empty the table body first
$.each(data,function(i,item){//loop each item from the json
$('#tableSellers tbody').append('<tr><td>'+item.StoreName+'</td><td><b>'+item.SaleNumber+'</b></td><td><b>'+item.Feedback+'</b></td></tr>');//build and append the html
});
});
});
});
I'm trying to create a table with child rows (always one child per row) acting as details section. In this details section users will be able to see a log history, and will also have the ability to input a specific log. Upon inputting a new log and clicking on the "Add" button, the log history should update and show the newly added event.
I have the following AJAX call that will be used to add a log and should refresh the details section, triggered after clicking on the "Add" button mentioned above:
$('#addLog').click(function () {
formData = {
logType: logType.value, // Parameter to add a new log
logComments: logComments.value, // Parameter to add a new log
agent: agent.value // Parameter to add a new log
}
$.ajax({
url: '#Url.Action("AddLog", "AgentUser")',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(formData),
cache: false,
success: function (data) {
// Here I should refresh the the details section
// and clear the logType and logCommands inputs
}
});
});
In my controller:
[HttpPost]
public ActionResult AddLog(string logType, string logComments, string agent, AgentUserValidatePhoneIndexViewModel vm)
{
DoDbStuff();
// Here I need to update the view model and view without having to
// refresh the page, so that it shows the recently added event.
return View(vm);
}
My ViewModel:
public class AgentUserValidatePhoneIndexViewModel
{
public IEnumerable<AgentUserWithoutValidPhone> AgentUserWithoutValidPhoneList { get; set; }
}
My Model:
public class AgentUserWithoutValidPhone
{
private string phone;
private DateTime creationDate;
public string Agent { get; set; }
public string Phone
{
get
{
return phone;
}
set
{
phone = PhoneNumberUtil.GetInstance().Parse("+" + value, String.Empty).NationalNumber.ToString();
}
}
public DateTime CreationDate
{
get
{
return creationDate;
}
set
{
creationDate = value;
TimeSpan timeSpan = (DateTime.Now) - creationDate;
TimeGoneBy = (timeSpan.Days != 0 ? timeSpan.Days + "d " : String.Empty) + timeSpan.Hours + "h";
}
}
public string TimeGoneBy { get; set; }
public DateTime LastLogEventDate { get; set; }
public LogEventTypePhone LastLogEvent { get; set; }
public IEnumerable<AgentUsersLog> EventList { get; set; }
}
My view:
#foreach (var agentUser in Model.AgentUserWithoutValidPhoneList)
{
<tr data-toggle="collapse" data-target="#details" class="accordion-toggle">
<td>
<button class="btn btn-default btn-sm"><span class="glyphicon glyphicon-collapse-down"></span></button>
</td>
<td>
#agentUser.Agent
</td>
<td>
#agentUser.Phone
</td>
<td>
#agentUser.CreationDate
</td>
<td>
#agentUser.TimeGoneBy
</td>
<td>
#agentUser.LastLogEventDate
</td>
<td>
#agentUser.LastLogEvent.GetDescription()
</td>
</tr>
<tr>
<td colspan="12" class="hiddenRow" id="">
<div class="accordian-body collapse" id="details">
<table class="table table-striped">
<thead>
<tr>
<input type="hidden" id="agent" value='#agentUser.Agent'>
<td>
#Html.DropDownList("LogEventTypePhone", EnumHelper.GetSelectList(typeof(Enums.LogEventTypePhone)), "Select log event",
new
{
id = "logType",
#class = "form-control"
})
</td>
<td colspan="2">
<input type="text" class="form-control" placeholder="Comments" id="logComments">
</td>
<td>
<a href="#" class="btn btn-default btn-sm" id="addLog">
<i class="glyphicon glyphicon-plus"></i>
</a>
</td>
</tr>
<tr>
<th>Event date</th>
<th>Event type</th>
<th>Comments</th>
<th>User</th>
</tr>
</thead>
<tbody>
#foreach (var e in agentUser.EventList)
{
<tr>
<td>#e.Date</td>
<td>#(((Enums.LogEventTypePhone)e.Subtype).GetDescription())</td>
<td>#e.Comments</td>
<td>#e.AspNetUsers.UserName</td>
</tr>
}
</tbody>
</table>
</div>
</td>
</tr>
}
How do I pass my ViewModel into my controller action, together with the parameters? Right now it's empty by the time I get to the action. I need to pass it into the action, interact with the DB, update the ViewModel, return to the View and have it updated with the current ViewModel.
I've never done what I'm trying to do here and I'm confused about it. Not sure if it's even possible, or maybe I should use several ViewModels.
There is no need to pass the view model to the controller and back again (it would just unnecessarily degrade performance). If your just wanting to add a new row based on the values you post to your controller method, then create a anonymous object (or a new instance of AgentUsersLog) containing the values to be shown in the new row, return it as json and update the DOM by adding a new <tr> element.
There are a few other issues with you code including the fact your creating invalid html (duplicate id attributes) in your foreach loops. Remove the id attributes and use class names instead in conjunction with relative selectors (the code you have shown will only ever handle the .click() event of the first link with id="addLog"). You view code should be
#foreach (var agentUser in Model.AgentUserWithoutValidPhoneList)
{
<tr data-toggle="collapse" data-target=".details" class="accordion-toggle">
....
</tr>
<tr>
<td colspan="12" class="hiddenRow">
<div class="accordian-body collapse details"> // use class name
<table class="table table-striped">
<thead>
<tr>
<td>
<input type="hidden" class="agent" value='#agentUser.Agent'> // must be inside a td element
#Html.DropDownList("LogEventTypePhone", EnumHelper.GetSelectList(typeof(Enums.LogEventTypePhone)), "Select log event", new
{
id = "", // remove id
#class = "form-control logType" // add class name
})
</td>
<td colspan="2">
<input type="text" class="form-control logComments" placeholder="Comments"> // use class name
</td>
<td>
<a href="#" class="btn btn-default btn-sm addLog"> // use class name
<i class="glyphicon glyphicon-plus"></i>
</a>
</td>
</tr>
<tr>
....
</tr>
</thead>
<tbody>
#foreach (var e in agentUser.EventList)
{
....
}
</tbody>
</table>
</div>
</td>
</tr>
}
And the script becomes
var url = '#Url.Action("AddLog", "AgentUser")';
$('.addLog').click(function () {
var table = $(this).closest('table');
var logType = table.find('.logType').val();
var logComments = table.find('.logComments').val();
var agent = table.find('.agent').val();
$.post(url, { logType: logType, logComments: logComments, agent: agent }, function(data) {
var row = $('<tr></tr>');
row.append($('<td></td>').text(data.Date));
.... // add other cells for data.Subtype, data.Comments and data.UserName
table.children('tbody').append(row);
});
});
Then in the controller
[HttpPost]
public JsonResult AddLog(string logType, string logComments, string agent)
{
DoDbStuff();
// Build the data to return
var data = new
{
Date = .... ,
Subtype = .... ,
Comments = ..... ,
UserName = ....
};
return Json(data);
}
You can acheive this by creating child object. Lets assume the model "AgentUserValidatePhoneIndexViewModel" has the below properties
Phone (int)
AgentDetail (string)
then generate formData as follows
formData = {
logType: logType.value, // Parameter to add a new log
logComments: logComments.value, // Parameter to add a new log
agent: agent.value // Parameter to add a new log
vm : { // Parameter to add values to view model
phone : answer.value,
agentDetail : agentDetail.value
}
}
Check this post to know how to render partial views
This post explains https://www.simple-talk.com/dotnet/asp.net/revisiting-partial-view-rendering-in-asp.net-mvc/
I have a situation where i am using angularJs smart table for filtering.
html:
<section class="main" ng-init="listAllWorkOrderData()">
<table st-table="listWorkOrderResponse">
<thead>
<tr>
<th st-sort="id">ID <i></i></th>
<th st-sort="project">Project <i></i></th>
</tr>
</thead>
<tbody ng-repeat="workOrder in listWorkOrderResponse">
<tr>
<td>{{workOrder.id}}</td>
<td>{{workOrder.project}}</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</section>
I am testing for 2 different cases.
In my controller first i call the same function but send dummy array and in the second case i send the array received from the api call.
1. Dummy data
$scope.listAllWorkOrderData = function () {
var listWorkOrderResponse = [{"id":"1","project":"project1"},{"id":2,"project":"project2"},{"id":"3","project":"project3"}];
}
2. I am using a service and fetching data through api.
$scope.listAllWorkOrderData = function () {
TestService.listAllWorkOrderData().then(function (response, status, headers, config) {
if (response != undefined && response != null) {
if (!$scope.listWorkOrderResponse) {
$scope.listWorkOrderResponse = [];
}
$scope.listWorkOrderResponse = response;
}, function (response, status, headers, config) {
console.log(response);
});
When i am using case1 the sorting works fine.
But when i use case2 the sorting does not work. Onclick of it the data just disappears.
I tried debugging to see whether the listAllWorkOrderData function is being called again when we click on the filter.But it is just called once when the page is loaded to populate the table.So that means the data is present in the listWorkOrderResponse. Then why is it not sorting?
I checked the response for both the situation by printing them the only difference i found was that the listWorkOrderResponse which comes from the api call has a $$hashKey: "object:363" added to it.
Can anyone point me what mistake i am doing.
I was able to resolve this issue by using stSafeSrc attribute
In the controller we add
$scope.listAllWorkOrderData = function () {
TestService.listAllWorkOrderData().then(function (response, status, headers, config) {
if (response != undefined && response != null) {
if (!$scope.listWorkOrderResponse) {
$scope.listWorkOrderResponse = [];
}
$scope.listWorkOrderResponse = response;
// we add one more list.
$scope.displayedWOList = [].concat($scope.listWorkOrderResponse);
}, function (response, status, headers, config) {
console.log(response);
});
and then in the html table we add the stSafeSrc attribute.
stSafeSrc attribute from the Smart Table document
http://lorenzofox3.github.io/smart-table-website/
stSafeSrc attribute
If you are bringing in data asynchronously (from a
remote database, restful endpoint, ajax call, etc) you must use the
stSafeSrc attribute. You must use a seperate collection for both the
base and safe collections or you may end up with an infinite loop.
<section class="main" ng-init="listAllWorkOrderData()">
<table st-table="displayedWOList" st-safe-src="listWorkOrderResponse">
<thead>
<tr>
<th st-sort="id">ID <i></i></th>
<th st-sort="project">Project <i></i></th>
</tr>
</thead>
<tbody ng-repeat="workOrder in displayedWOList">
<tr>
<td>{{workOrder.id}}</td>
<td>{{workOrder.project}}</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</section>
Why it is not working i don't know but yo can solve it by doing like below
repeat your response & create a new object & push it into an array..
var res = [];
for(var i=0; i<response.length; i++) {
var x = {"id":response[i].id, "project":response[i].project};
arr[i] = angular.copy(x);
}