React submit form to process AJAX request from checkbox input - html

I'm building a react contact list component that lists contacts and their data.
For one column I want checkboxes to allow the user to check off the contact he wishes to delete. For those that are checked off, the form should collect the corresponding contact's id and then pass it to an AJAX call to post those id's in a delete to the backend API. I'm stuck with what I have below and main problem is
1) building out form correctly to collect contact id's through checkboxes
[how do I wrap the checkboxes in a form when they belong to different rows in a table?]
2) passing those ids to a AJAX call
[how do I retrieve the data from a submitted form?]
render: function () {
var contacts = this.state.contacts.map(function (contact, idx) {
return (
<tr key={idx}>
<td>{contact.firstName}</td>
<td>{contact.lastName}</td>
<td>{contact.city}</td>
<td>{contact.phone}</td>
<td>{contact.email}</td>
<td><input type="checkbox" name="delete" value={contact.id}/></td>
</tr>
);
});
return(
<div>
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>City</th>
<th>Phone Number</th>
<th>Email</th>
<th>Delete</th>
</tr>
</thead>
<tbody>{contacts}</tbody>
</table>
</div>
);
}

Related

How I can send parameter to a JSP servlet with a c:forEach form? [duplicate]

This question already has an answer here:
How do I pass current item to Java method by clicking a hyperlink or button in JSP page?
(1 answer)
Closed 2 years ago.
I have a problem mixing JSP Servlet and c:forEach form...
The problem is that whatever my id is, the HTML form will always send the first in the list, refered to ' name="id" '.
Is there a solution maybe to get several name="id1", name="id2" ...etc in order to get the good one ?
Here is the code.
<div id="client-table">
<form action="gestion-commandes" method="POST">
<table class="table table-striped">
<thead class="thead-custom">
<tr>
<th scope="col">#</th>
<th scope="col">NOM</th>
<th scope="col">PRENOM</th>
<th scope="col">EMAIL</th>
<th scope="col">TEL</th>
<th scope="col">COMMANDES</th>
</tr>
</thead>
<tbody class="tbody-custom">
<c:forEach items="${clients}" var="client">
<tr>
<th scope="col">${client.id}<input name="id" value="${client.id}" hidden = "true"></th>
<th scope="col">${client.nom}</th>
<th scope="col">${client.prenom}</th>
<th scope="col">${client.email}</th>
<th scope="col">${client.tel}</th>
<th scope="col"><button type="submit">Commandes</button>
</th>
</tr>
</c:forEach>
</tbody>
</table>
</form>
</div>
</div>
Thank you in advance,
Joss
When the parameter has multiple values, using request.getParameter("id") will return only the first parameter value.
You can get all values using request.getParameterValues instead of request.getParameter, for example:
String[] ids = request.getParameterValues("id");
But, if you only want to get one value, corresponding to the row you clicked, you can't use a hidden input, because all hidden inputs will be send with the submit.
The most straight forward way to get only the selected id is to pass it as a value of the button. Only the clicked button will be send with the submit.
<button type="submit" name="selected" value="${client.id}">Commandes</button>
And getting it on your servlet with:
String selectedId = request.getParametre("selected");
You will find more details on this answer of question marked as duplicate.

Sinatra & Angular $HTTP.delete 404

Trying to delete from my API which is hosted on Heroku.
In Ruby file CROSS-ORIGIN is enable and I can get information from my API.
Although I have a problem when I want to make a delete request to the server.
I get an error 404 (Page not found), but when typing the url into the browser myself I can easily get this page.
cURL call works fine without any problems too.
script.js
$scope.DeleteData = function (index) {
$scope.id = $scope.companies[index].companyID;
var deleteUrl = 'https://*****.herokuapp.com/api/v1/companies/' + $scope.id;
$http.delete(deleteUrl,'DELETE').then(function(response){
console.log(response);
},function(errorResponse){
console.log(errorResponse);
});
};
Ruby.rb
delete '/companies/:companyID' do
tempCompanyID = params['companyID']
company = Company.where(companyID: tempCompanyID).first
company.destroy
end
Html:
<div ng-app="myApp" ng-controller="companyCtrl">
<table class="table table-striped table-hover">
<thead class="thead-dark">
<th>Company ID</th>
<th>Company Name</th>
<th>Address</th>
<th>City</th>
<th>Country</th>
<th>Owners</th>
<th></th>
</thead>
<tr ng-repeat="company in companies">
<td>{{company.companyID}}</td>
<td>{{company.companyName}}</td>
<td>{{company.address}}</td>
<td>{{company.city}}</td>
<td>{{company.country}}</td>
<td>{{company.owners}}</td>
<td><button class="btn" name="_method" ng-click="DeleteData($index)">Delete</button></td>
</tr>
</table>
</div>
Chrome response:
The response

Angular 5 Datatables pop up a warning alert when re render

I had succeed on creating a table and implement datatable on my angular 5 project
html code for the table:
<table class="table table-hover mt-3" datatable [dtOptions]="dtOptionsContent" [dtTrigger]="dtTriggerContent">
<thead>
<tr>
<th scope="col">Content Type</th>
<th scope="col">User Occupation</th>
<th scope="col">Content Name</th>
<th scope="col">Carrot</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let reward of rewards" >
<td data-toggle="modal" data-target="#seeDetail" (click)="onSelect(reward)">{{getRewardType(reward.type)}}</td>
<td data-toggle="modal" data-target="#seeDetail" (click)="onSelect(reward)">{{getRoleType(reward.role)}}</td>
<td data-toggle="modal" data-target="#seeDetail" (click)="onSelect(reward)">{{reward.name}}</td>
<td data-toggle="modal" data-target="#seeDetail" (click)="onSelect(reward)">{{reward.carrot}}</td>
</tr>
</tbody>
</table>
.ts code for the datatable settings:
dtOptionsContent: DataTables.Settings = {};
dtTriggerContent: Subject<any> = new Subject();
#ViewChild(DataTableDirective)
dtElementContent: DataTableDirective;
.ts for get rewards:
getRewards(): void
{
this.adminService.getRewards().subscribe(rewards=> {
this.rewards = rewards;
this.dtTriggerContent.next();
});
}
The sorting, pagination, and searching are functional and when i add/delete a content to the table , the table is updated.
However, after updated, when i tried the sorting and pagination, the table content revert to the pre-added/deleted list.
I've tried destroy and rerender the table. This is the .ts code for adding content:
addSocial(role: number, rewardName: string, carrot: number): void
{
this.dtElementContent.dtInstance.then((dtInstance: DataTables.Api) => {
let currentCarrot = 0;
if(!isNaN(carrot))
{
//Setting for rewardTemp goes here
this.adminService.addReward(this.rewardTemp)
.subscribe(reward => {
dtInstance.destroy();
this.rewards.push(reward);
this.dtTriggerContent.next();
});
//Success Notification goes here
}
else
//Error Notification goes here
});
}
while it succeed to sorting the updated content after the list was updated, it spawn warning alert after rerender.
The alert contains "DataTables warning: table id=DataTables_Table_1 - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3"
What is wrong??

Pagination not working when Dynamic result is displayed to datatable <tbody>

using a datatable (bootstrap )
i am displaying the result of ajax in part of datatable . the result ged addded to datable but
pagination not working on new result as the page loads only once.Who the pagination will work on new displayed result.
Thanks in advance.
<script>
$(document).ready(function () {
$('.dataTables-example').dataTable();
});
var data = $.parseJSON(responseData);
var tbl_op ='';
$.each(data.result,function(k,v){
console.log(v.id);
$('.dataTables-example').dataTable();
tbl_op +="<tr class='odd gradeX'>"+
'<td>'+v.id+'</td>'+
'<td>'+v.country_name+'</td>'+
'<td>'+v.created+'</td>'+
'<td>'+'Edit</td>'+
'</tr>';
});
$('#country_list').html(tbl_op);
$('#Response').fadeIn(1000);
$('#Response').html(data.response_msg);
$('#Response').fadeOut(8000);
</script>
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover dataTables-example" id="dataTables-example">
<thead>
<tr>
<th>Id</th>
<th>Country</th>
<th>Date</th>
<th>Action</th>
</tr>
</thead>
<tbody id='country_list'>
</tbody>
</table>
</div>
result:
<tbody id="country_list"><tr class="odd gradeX"><td>1</td><td>India</td><td>2016-09-13 11:33:30</td><td>Edit</td></tr><tr class="odd gradeX"><td>2</td><td>Usa</td><td>2016-09-13 11:33:30</td><td>Edit</td></tr><tr class="odd gradeX"><td>3</td><td>Russia</td><td>2016-09-13 11:33:30</td><td>Edit</td></tr><tr class="odd gradeX"><td>4</td><td>R1</td><td>2016-09-13 11:33:42</td><td>Edit</td></tr><tr class="odd gradeX"><td>5</td><td>R5</td><td>2016-09-13 11:34:30</td><td>Edit</td></tr><tr class="odd gradeX"><td>6</td><td>R6</td><td>2016-09-13 11:34:40</td><td>Edit</td></tr><tr class="odd gradeX"><td>7</td><td>R7</td><td>2016-09-13 11:34:48</td><td>Edit</td></tr><tr class="odd gradeX"><td>8</td><td>R8</td><td>2016-09-13 11:34:54</td><td>Edit</td></tr><tr class="odd gradeX"><td>9</td><td>R9</td><td>2016-09-13 11:35:00</td><td>Edit</td></tr><tr class="odd gradeX"><td>10</td><td>R10</td><td>2016-09-13 11:35:07</td><td>Edit</td></tr><tr class="odd gradeX"><td>11</td><td>R11</td><td>2016-09-13 11:35:13</td><td>Edit</td></tr><tr class="odd gradeX"><td>12</td><td>R12</td><td>2016-09-13 11:35:25</td><td>Edit</td></tr><tr class="odd gradeX"><td>13</td><td>R67</td><td>2016-09-13 11:37:30</td><td>Edit</td></tr></tbody>
In order to have pagination updated on XHR requests, you need to have the information about the pagination as well. That is:
Current page number
Total amount of entries
The amount of entries to show per page
This information should be returned with your XHR request. You could for example add these properties to your result object (result.currentPage, result.totalPages, result.totalEntries).
Now with each concurrent request you should send these parameters to the server, and the server should fetch the proper dataset according to these parameters.
And last but not least, with this data you can re-calculate the state of your pagination element.
Another option:
If you download the complete dataset from the server (which seems to be the case in your example), you should keep the parameters required for pagination (entriesPerPage, currentPage, totalEntries) in your JavaScript code so you can keep track of your pagination state with that and update your pagination component as such.
Please be aware that downloading all data with one XHR request could possible lead a bottleneck in your application. Imagine with a dataset with tens of thousands of records will do with your bandwidth, or even worse: with the memory consumed by JavaScript. That's why I would suggest option #1.

How to pass arguments from input controls to xquery function and call it on button press?

I created xquery function which returns a table:
declare function local:table($collection as xs:string*, $interface as xs:string?, $date as xs:string?) as node() {
<table border="1">
<thead>
<tr>
<th>Inteface Name</th>
<th>Test Date</th>
<th>Test Result</th>
<th>Report Link</th>
</tr>
</thead>
<tbody>
{
for $child in xmldb:get-child-resources($collection)
let $doc := fn:doc(fn:concat($collection, '/', $child))
where (fn:ends-with($child, '.xml'))
and (($doc//*:interfaceName/text() eq $interface) or empty($interface))
and (($doc//*:reportDate/text() eq $date) or empty($date))
order by $doc//*:reportDate/text() descending
return
<tr>
<td>
{$doc//*:interfaceName/text()}
</td>
<td>
{$doc//*:reportDate/text()}
</td>
<td>
{$doc//*:testResult/text()}
</td>
<td>
<li>
<!--{$child} -->
{$child}
</li>
</td>
</tr>
}
</tbody>
</table>
I also added a few input controls on the page. One of them looks like:
<InterfaceName constraint="true" readonly="false" required="false" relevant="true">
<value>test</value>
</InterfaceName>
<xf:bind nodeset="InterfaceName">
<xf:bind nodeset="value" type="string"/>
<xf:input id="InterfaceName" ref="InterfaceName/value" incremental="true">
<xf:label></xf:label>
<xf:hint>xxxxxYYYZZZ</xf:hint>
<xf:help>Enter interface name</xf:help>
<xf:alert>Enter interface name</xf:alert>
</xf:input>
I also added a button to the webpage:
<trigger1 constraint="true" readonly="false" required="false" relevant="true">
<value></value>
</trigger1>
<xf:submission id="s-send"
replace="instance"
resource="echo:test"
method="get">
</xf:submission>
<div>
<xf:trigger id="trigger1" ref="trigger1/value" incremental="true">
<xf:label>Filter output</xf:label>
<xf:hint>a Hint for this control</xf:hint>
<xf:help>help for trigger1</xf:help>
<xf:send submission="s-send"/>
</xf:trigger>
</div>
On this button click I need to somehow pass parameters form those input controls to xquery function and return the table to the webpage. Entire webpage is of type xQuery (it builds html) and run with eXist-db.
Could you help me with this, please?
Thank you.
You'll need four elements to achieve your goal:
An <xf:instance id="result" > to store the result of calling your xquery. Make sure to add an id attribute to identify the instance further.
An <xf:submission> to call your xquery an store the result in the instance. This is the submission you'll call in the <xf:send> and may look like this:
<xf:submission id="s-send" method="get" replace="instance" instance="result">
<xf:resource value="concat('myxquery.xq?interface=',InterfaceName/value)"/>
</xf:submission>
Note that the concat function is used to build the xquery url, including parameters.
An <xf:output value="instance('result')" mediatype="application/xhtml+xml"> to show the contents of the result instance. The mediatype="application/xhtml+xml" attribute is needed to display the html table.
In the server side, you can't call an xquery function directly, you need to write an xquery (myquery.xq) that calls the function and extracts the parameters from the URL.
Take a look to this sample https://en.wikibooks.org/wiki/XQuery/Getting_URL_Parameters