How multiple Row Selection in react js?(ctrl +click) and (shift +click) - reactjs

Code-:
const ClickHighlight = (event, id) => {
if (event.ctrlKey) {
// add to highlighted
setHighlightedRows((current) => {
if (current.includes(id)) {
// row is already highlighted. Unhighlight but keep the others
return current.filter((entry) => entry !== id);
} else {
// add row to the current list of highlighted ones
console.log("nn", ...current, id);
return [...current, id];
}
});
} else if (event.shiftKey) {
event.preventDefault();
previousRow = id;
// add to highlighted
setHighlightedRows((current) => {
if (current.includes(id)) {
// row is already highlighted. Unhighlight but keep the others
// console.log("shift", current);
return current.filter((entry) => entry !== id);
}
else {
// add row to the current list of highlighted ones
console.log("else", id);
console.log("elsecurrent", current);
return [...current, id];
}
});
}
else {
// highlight clicked row and de-highlight others
setHighlightedRows([id]);
}
}
table:-
<tr key={comment.idx} tabIndex={comment.idx} className="border_bottom" onKeyDown={(e) => handleKeyDown(e, comment.idx)} onLoad={() => active(comment.idx)}
ref={comment.idx === 0 ? myRef : null}
onMouseDown={(e) => ClickHighlight(e, comment.idx)}
style={isHighlighted ? { backgroundColor: '#254368' } : {}}>
<td style={{ color: "white", width: "200px" }}>
<img src={`data:image/jpeg;base64,${base64}`} alt="Clip Thumbnail" width="50%" />
</td>
<td style={{ color: "white", width: "440px" }}>{comment.ClipName}</td>
please help I want when users click the shift + mouse click than 1 row and 2 last rows. All rows selected btw them with the index number number
please help...
If user press shift + left click from 1 row to 2 last row then all row btw one and 2 last became selected/focused right now only ctrl + mouse click is working so how can i do the shift + click in react js

Related

MultiSelect in material ui not selecting values properly

I need help with the following code.
The values being selected are messed up. They are not right. Some of the elements get selected twice or more times. some don't get selected at all.
function HelloWorld({
greeting = "hello",
greeted = '"World"',
silent = false,
onMouseOver,
}) {
if (!greeting) {
return null;
}
// TODO: Don't use random in render
let num = Math.floor(Math.random() * 1e7)
.toString()
.replace(/\.\d+/gi, "");
return (
<div
className="HelloWorld"
title={`You are visitor number ${num}`}
onMouseOver={onMouseOver}
>
<strong>
{greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()}
</strong>
{greeting.endsWith(",") ? (
" "
) : (
<span style={{ color: "grey" }}>", "</span>
)}
<em>{greeted}</em>
{silent ? "." : "!"}
</div>
);
}

Why everytime page react re-renders checkbox within map gets checked by default?

I have a table that gets populated by an ticketArray array of objects brought from an api.
Every object gets a final column of type checkbox
Every time I click on the checkbox I add that object ID to a "toDeleteRow" array.
And only when the Button Delete is clicked I loop through ticketArray comparing every item id against ids in toDeleteRow. If ids are equal I delete that object from ticketArray and I wipe out toDeleteRow
The problem is when the page gets re-render the first of the remaining rows gets checked by default (and internally gets added to the toDeleteRow WHICH I don't want to)
<tbody>
{ticketArray.map((ticket: any, index) => (
<tr key={index}>
<td>{ticket.Id}</td>
<td>{ticket.createdDate}</td>
<td>PR</td>
<td>
<i className="icon-edit icon-large" title="Edit" onClick={handlePopupModifShow} />
</td>
<td>
<input onChange={() => { AddToRemove(ticket.Id) }}
className="form-check-input" type="checkbox"></input>
</td>
</tr>
))}
</tbody>
This are my functions:
const AddToRemove= (id: string) => {
if (toDeleteRow.includes(id)) {
let val = toDeleteRow.indexOf(id, 0)
if (val> -1) { toDeleteRow.splice(val, 1); }
}
else { toDeleteRow.push(id) }
}
const Remove = () => {
if (toDeleteRow.length > 0) {
let newArray: SetStateAction<{ Id: string; createDate: string }[]> = []
for (let x = 0; x < toDeleteRow.length; x++) {
newArray = ticketArray.filter(function (obj) {
return obj.Id !== toDeleteRow[x];
});
}
setTicketArray(newArray)
toDeleteRow.splice(0, toDeleteRow.length)
}
else {
alert("Select at least one row")
}
}
Any suggestions? It's driving me nuts :S

Conditionally use react imports

I have these three imports and I want to use them accordingly.
import avatar1 from "../../../../assets/images/user/avatar-1.jpg";
import avatar2 from "../../../../assets/images/user/avatar-2.jpg";
import avatar3 from "../../../../assets/images/user/avatar-3.jpg";
And I have this map function and I want to show these three images as map function executes.
So I wrote this:
{this.state.empData.map((emp, index) => (
<tr className="unread" key={emp.id}>
<td>
{index + 1 <= 3 ? (
<img
className="rounded-circle"
style={{ width: "40px" }}
src={`avatar` + { index }}
alt="activity-user"
/>
) : (
(index = 0) // i want to reset the index, so it would start from 0 again
)}
</td>
</tr>
))}
So what i want is, if I have 10 iterations through that map function, and I have 3 avatars, I want to show each 10 image so each 3 avatars are repeated from avatar1 to avatar3 as long as map iterates.
Above method I tried, doesn't work as images a re not showing.
Can you help me?
Write a selector function and use the modulus
You can use modulus to repeat a series of numbers. it always returns the remainder of the division. e.g. 3 % 3 === 0 6 % 3 === 0 1 % 3 === 1
const selectImage = (index) {
if (index % 3 === 0) {
return avatar1; // or return "../../../../assets/images/user/avatar-1.jpg"
}
if (index % 3 === 1) {
return avatar2; // or return "../../../../assets/images/user/avatar-2.jpg"
}
if (index % 3 === 2) {
return avatar3; // or return "../../../../assets/images/user/avatar-3.jpg"
}
}
and then in your component
<img
className="rounded-circle"
style={{ width: "40px" }}
src={selectImage(index)}
alt="activity-user"
/>

last row is being deleted instead of clicked row in ReactJS

I want to delete a row from html table on button click using ReactJS. The problem is that on clicking delete button always last row is being deleted instead of the row that is clicked. Please tell what is the issue with my code?
code:
var RecordsComponent = React.createClass({
getInitialState: function() {
return {
rows: ['row1', 'row2', 'row3'],
newValue: "new value"
}
},
render : function() {
return (
<div>
<table>
<tbody>
{this.state.rows.map((r) => (
<tr>
<td>{r}</td>
<td>
<button onClick={this.deleteRow}>Delete</button>
</td>
</tr>
))}
</tbody>
</table>
<input trype="text" id={"newVal"} onChange={this.updateNewValue}></input>
<button id="addBtn" onClick={this.addRow}>ADD</button>
</div>
);
},
updateNewValue: function(component) {
this.setState({
newValue: component.target.value
});
},
addRow : function() {
var rows = this.state.rows
rows.push(this.state.newValue)
this.setState({rows: rows})
},
deleteRow : function(record) {
var index = -1;
var clength = this.state.rows.length
for( var i = 0; i < clength; i++ ) {
if( this.state.rows[i].value === record.target.value ) {
index = i;
break;
}
}
var rows = this.state.rows
rows.splice( index, 1 )
this.setState( {rows: rows} );
}
});
React.render(<RecordsComponent/>, document.getElementById('display'))
You need pass a param on func deleteRow
<button onClick={() => this.deleteRow(r)}>Delete</button>
I refactor a litte bit of your func
deleteRow : function(record) {
this.setState({
rows: this.state.rows.filter(r => r !== record)
});
}
In deleteRow you are looking for the index of the row that matches record.target.value (record is actually an event), but event.target.value is blank so the index remains -1, and rows.splice(-1, 1) deletes the last element.
You should pass the row data itself, like:
<button onClick={e => this.deleteRow(r)}>Delete</button>

Scroll through table rows programmatically

The objective of this plunk is to have a table where the up and down keys will be used to select rows programmatically and scroll through the table. The selected row will have a different background color.
When keying up/down I use e.preventDefault() to avoid the rows to move up/down twice. Problem is that when I start scrolling down the rows stay fixed and the selected row disappears. How to fix this?
HTML
<div id="selector" tabindex="0" ng-keydown="scroll($event)"
style="width:300px;height:80px;border:1px solid gray;overflow-y:auto">
<table>
<tr ng-repeat="item in items">
<td class="td1" ng-class="{'tdactive' : $index==index }">{{item.col}}</td>
<td class="td1" ng-class="{'tdactive' : $index==index }">{{item.dsc}}</td>
</tr>
</table>
</div>
Javascript
var app = angular.module('app', []);
app.controller('ctl', function($scope) {
document.getElementById("selector").focus();
$scope.items = [ {col:"aaa", dsc:"AAA1"}, {col:"bbb", dsc:"BBB2"} , {col:"ccc", dsc:"CCC3"},
{col:"aaa2", dsc:"AAA21"}, {col:"bbb2", dsc:"BBB22"} , {col:"ccc2", dsc:"CCC23"},
{col:"aaa2", dsc:"AAA21"}, {col:"bbb2", dsc:"BBB22"} , {col:"ccc2", dsc:"CCC23"} ];
$scope.index = 0;
$scope.scroll = function(e) {
if (e.which === 40) { // down arrow
if ($scope.index<$scope.items.length - 1)
$scope.index++;
e.preventDefault();
}
else if (e.which === 38) { // up arrow
if ($scope.index>0)
$scope.index--;
e.preventDefault();
}
};
});
First of all you need to add table row id as id="tr-{{$index}}"
You can then prevent your scroll if tr is in the current viewport
$scope.scroll = function(e) {
var parentContainer = document.getElementById("selector");
if (e.which === 40) { // down arrow
if ($scope.index<$scope.items.length - 1)
{
var element = document.getElementById("tr-"+$scope.index);
if(isElementInViewport(parentContainer,element)){
e.preventDefault();
}
$scope.index++;
}
}
else if (e.which === 38) { // up arrow
if ($scope.index>0)
{
var element = document.getElementById("tr-"+$scope.index);
if(!isElementInViewport(parentContainer,element)){
e.preventDefault();
}
$scope.index--;
}
}
};
function isElementInViewport(parent, el) {
if(parent==undefined || el==undefined)
return false;
var elRect = el.getBoundingClientRect(),
parRect = parent.getBoundingClientRect();
//console.log(elRect)
//console.log(parRect)
var elementHeight = elRect.height;
return (
elRect.top >= parRect.top &&
elRect.bottom <= parRect.bottom &&
elRect.bottom+elementHeight<= parRect.bottom
);
}
Working Plunker

Resources