How to display duplicate array values only once in React.js - reactjs

I have a Bill To Print but in Bill I have 'Products' array object in which I want, I have 3 products array then product name, price, discount, etc. are same then it should show only one array (line) but in 'Products' array I have a 'SrNo.' column which means each product has unique serial number so it should product name, price, discount, etc. show in one line and 'SrNo.' column shows 3 rows. Currently I'm using map() to display array values but it showing like this
Products arrays
My Bill_Preview.js (Frontend)
<tr>
<td style={{width:"1%"}}>Sr<br></br>No.</td>
<td >Description Of Goods</td>
<td >Qty</td>
<td >Rate</td>
<td >Disc %</td>
<td >Amount</td>
</tr>
{/* Data row */}
{DataForPreview &&
DataForPreview.map((data, Id) => (
// This Row all data i want only once if its same product except 'Prod_SrNo'
<tr>
<td >{Id + 1}.</td>
<td >
{data.Product_Comp} {data.Product}
<br></br>
{data.Prod_SrNo}
<br></br>
</td>
<td >1</td>
<td >{data.Price}</td>
<td >{data.Discount}</td>
<td >{(data.Price - (data.Price * data.Discount) / 100).toFixed(2) }</td>
</tr>
))}

you can filter the duplicate values from the array before mapping:
function filterDuplicates(arr){
return arr.filter((item, index) => arr.findIndex(data=> data.Product === item.Product && data.Product_Comp === item.Product_Comp) === index);
}
function findDuplicatesRows(data){
return DataForPreview.filter(item => (data.Product === item.Product && data.Product_Comp === item.Product_Comp))
}
filterDuplicates(DataForPreview).map((data, Id) => (
<tr>
<td >{Id + 1}.</td>
<td >
{data.Product_Comp} {data.Product}
<br></br>
{findDuplicatesRows(data).map(d => (
<tr>{d.Prod_SrNo}</tr>
))}
<br></br>
</td>
<td >1</td>
<td >{data.Price}</td>
<td >{data.Discount}</td>
<td >{(data.Price - (data.Price * data.Discount) /100).toFixed(2)}</td>
</tr>
))}
but you have to calc the total values of the duplicates, for example
calc the total amount
function calcTotalAmount(data){
const amount = (data.Price - (data.Price * data.Discount) /100).toFixed(2);
const quantity = findDuplicatesRows(data).length;
return amount * quantity;
}
<td>{calcTotalAmount(data)}</td>
I think there is a simpler way to do it,
but get the fundamental

Related

How do I display an array where each object in array is a new <td> in ReactJS

I have an array which contains multiple objects like this:
const locations = [
{
information: ["Data Analyst", "Uruguay", "Montevideo", "$30,000"],
},
{
information: ["CTO", "UK", "Manchester", "$75,000"],
}
];
And I want to display each array in a new table row containing a <td> with each string.
Currently I have done this:
<tr>
{locations.map((location) => <td>{location.information}</td>)};
</tr>
Which returns each piece of information on a <td>
This is how the data looks at the minute:
And how it's meant to look
For this you have to use Array.map() like:
// To create tha table body by iterating data array
{
locations.map((location, locationIndex) =>
<tr key={locationIndex}>
<td>{location.information[0]}</td>
<td>{location.information[1]}</td>
<td>{location.information[2]}</td>
<td>{location.information[3]}</td>
</tr>
)
}
// In case you don't want to harcode the array index
{
locations.map((location, locationIndex) =>
<tr key={locationIndex}>
location.information.map((loc, locIndex) =>
<td key={locIndex}>{loc}</td>
)
</tr>
)
}
Change the code from,
<tr>
{locations.map((location) => <td>{location.information}</td>)};
</tr>
To:
<table border="1" width="100%" className="component_useRefBox">
<tbody>
{locations.map((location, i) => {
return (
<tr key={i}>
{location.information.map((data, j) => {
return <td key={j}> {data} </td>;
})}
</tr>
);
})}
</tbody>
</table>
To display two records row by row, you need to move {locations.map((location) .... )} above <tr> ... </tr> tag, because while using map method only each row will get iterated and you will get two separate rows..
{locations.map((location, i) => {
return (
<tr>
....
</tr>
)})}
As location.information is of array data, you cannot assign it directly.
You need to iterate using map and display each data like,
{location.information.map((data) => {
return <td> {data} </td>;
})}

Splitting single row into multiple rows using vanilla Table with reactjs

I am having trouble in fragmenting table rows from the JSON fetched data.
Code looks like below:
<table>
<thead>
<tr>
<th scope="col">Location ID #</th>
<th scope="col">Device Name</th>
</tr>
</thead>
<tbody>
{Object.keys(deviceList).map((key, index) => {
return (
<tr key={index}>
{deviceList[key].ports.map(port => port.value.id)
.map(ids => {
console.log("type", typeof(ids)) // it says number
return <td>{ids}</td>
})
}
</tr>
)
})}
</tbody>
</table>
actual result:
ID. Name.
23301 24401
99501 87701
22201
The above result is because one port can have multiple ID's but it shows that in parallel instead in the next row. So there are three ports and portA has two devices, portB has two devices and portC has just one.
expected result:
ID. Name.
23301
24401
99501
87701
22201
I could fix it by changing the way I was implementing it.
{Object.keys(deviceList).map(key => {
return deviceList[key].ports.map(port => {
return (
<tr>
<td> {port.value.siteId}</td>
<td>{port.value.name}</td>
<td>{deviceList[key].value.targetId === undefined ? deviceList[key].value.name : deviceList[key].value.targetId}</td>
<td>{deviceList[key].value._type}</td>
<td>{port.description === undefined ? deviceLookup[key].value.name : deviceList[key].value.name + ' ' + "[" + port.description + "]"}</td>
</tr>
)
})
})
}

display element (span tag ) after last ocurence of repeated item inside ng-repeat

I want to display something like this inside an ng-repeat: display a span tag saying the total purchase right after the last purchase of each person.( I do not want to display the total after each purchase). I have an array of object like this :
let group=[{name:'Brandon Pack',city:'NY',purchase:25,accepted:true},
{name:'Josh Vilet',city:'Memphis',purchase:30,accepted:true},
{name:'Brandon Pack',city:'NY',purchase:62,accepted:true},
{name:'Patrick Whiteside',city:'NY',purchase:50,accepted:false},
{name:'Josh Vilet',city:'Memphis',purchase:50,accepted:true}]
I can get the total, my problem is with the view that I don't want to display the total only after the last ocurence for that person
First of all, you can create a function in your controller in order to get the total amount:
$scope.getTotal = function () {
var sum = 0;
$scope.group.forEach(function(customer){
sum += customer.purchase;
});
return sum;
}
By the way, you can't declare variables with whitespaces in their name, like "let group", better call it "letGroup".
Then, you just have to create your table in Html:
<table>
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>Purchase</th>
<th>Accepted</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="o in group">
<td ng-bind="o.name"></td>
<td ng-bind="o.city"></td>
<td ng-bind="o.purchase"></td>
<td ng-bind="o.accepted ? 'Yes': 'No'"></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Total</td>
<td ng-bind="getTotal()"></td>
</tr>
</tbody>
</table>

Get the Dynamic table data from gui in selenium webDriver

I am working on a web based Application that I am testing with Selenium. On one page the content is dynamically loaded in table. I want to get the Table data, i am geting a "org.openqa.selenium.NullPointerElementException" in this line.
WebElement table = log.driver.findElement(By.xpath(tableXpath));
I tried the following complete code.
public int selectfromtable(String tableXpath, String CompareValue, int columnnumber) throws Exception {
WebElement table = log.driver.findElement(By.xpath(tableXpath));
List<WebElement> rows = table.findElements(By.tagName("tr"));
int flag = 0;
for (WebElement row : rows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
if (!cells.isEmpty() && cells.get(columnnumber).getText().equals(CompareValue)) {
flag = 1;
Thread.sleep(1000);
break;
} else {
Thread.sleep(2000);
flag = 0;
}
}
return flag;
}
I am calling the above method like
String tableXpath = ".//*[#id='event_list']/form/div[1]/table/tbody/tr/td/div/table";
selectfromtable(tableXpath, eventType, 3);
my html page is like
<table width="100%">
<tbody style="overflow: auto; background-color: #FFFFFF">
<tr class="trOdd">
<td width="2%" align="center">
<td width="20%" align="center"> Account </td>
<td width="20%" align="center"> Enter Collection </td>
<td width="20%" align="center">
<td width="20%" align="center"> 10 </td>
<td width="20%" align="center"> 1 </td>
</tr>
</tbody>
<tbody style="overflow: auto; background-color: #FFFFFF">
<tr class="trEven">
<td width="2%" align="center">
<td width="20%" align="center"> Account </td>
<td width="20%" align="center"> Resolved From Collection </td>
<td width="20%" align="center">
<td width="20%" align="center"> 10 </td>
<td width="20%" align="center"> 1 </td>
</tr>
</tbody>
</table>
My solution for similar case - I wanted to get a row number from table, which given column contains specific text.
// Method searches in given column of a table and return number of row where
// exactly first value is spotted (title row counts as 0 row and is
// skipped). If no value is found then 0 is returned. Given column number
// starts with 1.
public Integer getTableRowNumberWithValue(String tableId, String value,
Integer columnNumber) {
WebElement table = getDriver().findElement(By.id(tableId));
List<WebElement> rows = table.findElements(By.tagName("tr"));
int j = 0;
int i = 0;
for (WebElement row : rows) {
// Skip title row which counts as 0 row.
if (i > 0) {
if (row.findElements(By.tagName("td")).get(columnNumber - 1)
.getText().equals(value)) {
j = i;
break;
}
}
i++;
}
return j;
}
I had the similar issue. The solution I found was use the method and xpath together.
public void theSearch(String value) throws Exception {
String xpathExpression = "//*[starts-with(#id,'searchResultsTable:')]";
List<WebElement> elementTable= state.getDriver().findElements(By.xpath(xpathExpression));
for (WebElement listofElement : elementTable) {
String theElement= listofElement.getText();
if (theElement.contains(value)) {
Assert.assertEquals(value, theElement);
// System.out.println("The Expected Value " + value + " Equals the actual " + theElement);;
}
}
}

Disable and Enable Checkboxes Javascript

I have a series of Checkboxes:
<tr id="tr5" onmouseover="changeBackgroundColor(this.id)" onmouseout="changeBackgroundColor2(this.id)">
<td class="td5"><input name="benefit" value="Bonuses" id="benefit5" type="checkbox" onchange='addition();'</td>
<td class="td5"><label for="benefit5"> <b>Bonuses</b></label></td>
<tr id="tr6" onmouseover="changeBackgroundColor(this.id)" onmouseout="changeBackgroundColor2(this.id)">
<td class="td6"><input name="benefit" value="Final salary pension" id="benefit6" type="checkbox" onchange='addition();'</td>
<td class="td6"><label for="benefit6"> <b>Final salary pension</b></label></td>
Once a user has selected 3 checkboxes, is it possible to disable the rest in one hit (there are 30 checkboxes - I could do it individually but that seems a pain)? Is so, how would one go about doing that? Also, if the user then un-selected one of the check boxes, is it possible to enable them again?
EDIT: If possible - could someone point me in the right direction, code wise please?
Thanks in advance,
H.
DEMO
var chk=0;
function checkCheckboxes() {
var checkboxes = document.getElementsByName("benefit");
for (var i=0;i<checkboxes.length;i++) {
chk += checkboxes[i].checked?1:0; // count in case we reload
checkboxes[i].onclick=function() { // set up event handler for each
chk+=this.checked?1:-1; // add or subtract one
if (chk > 3) {
console.log(chk,"too many")
this.checked=false;
chk--; // we counted too many
}
}
}
}
function changeBackgroundColor(row,on) {
var id = row.id; // if you need that
row.style.backgroundColor=(on)?"red":"white";
}
window.onload=function() {
var trs = document.getElementById("table1").rows;
for (var i=0;i<trs.length;i++) {
trs[i].onmouseover=function() {
changeBackgroundColor(this,1);
}
trs[i].onmouseout=function() {
changeBackgroundColor(this,0);
}
}
checkCheckboxes();
}
using
<table id="table1">
<tr id="tr1">
<td class="td1"><input name="benefit" value="Bonuses" id="benefit1" type="checkbox"</td>
<td class="td1"><label for="benefit1"> <b>Bonuses</b></label></td>
</tr>
<tr id="tr2">
<td class="td2"><input name="benefit" value="Bonuses" id="benefit2" type="checkbox"</td>
<td class="td2"><label for="benefit2"> <b>Bonuses</b></label></td>
</tr>
<tr id="tr3">
<td class="td3"><input name="benefit" value="Bonuses" id="benefit3" type="checkbox"</td>
<td class="td3"><label for="benefit3"> <b>Bonuses</b></label></td>
</tr>
<tr id="tr4">
<td class="td4"><input name="benefit" value="Bonuses" id="benefit4" type="checkbox"</td>
<td class="td4"><label for="benefit4"> <b>Bonuses</b></label></td>
</tr>
</table>

Resources