React make items swap in 2 list - javascript

I'm trying to make item swap in 2 array. There are 2 lists in the ui and the user select the
items in the first list, then it should get removed from the 1st list and moved to 2nd list, where there are shown the selected items. The problem I got is that when I try to move the elements from the 1st and 2nd list with the setValue it doesen't change the value value.
The function getIndexA works, I use it because I have an array of object and in the input as value I have a proprierty of the object (the key).
(If I print array before removing the object and after removing the object I see the array is correctly removing the object but when I setListaFile it doesen't change ListaFile values (even if I uncheck and recheck the input I see that array2 is made of the element selected and undefined) so it seems to work, but in render I still se the list as same of start (even with an useState connected to listaFile with a console log it doesen't show the console log of listaFile)
const [fileSelezionati,setFileSelezionati] = useState([]);
const [listaFile,setListaFile] = useState([]);
function handleCheck(e){
if(e.target.checked){
var array = listaFile;
var item = listaFile[getIndexA(listaFile,e.target.value)];
array.splice(getIndexA(listaFile,e.target.value),1);
setListaFile(array);
var array2 = fileSelezionati;
array2.push(item);
console.log("array2:",array2);
setFileSelezionati(array2);
}
}
This part is in the return()
<ul>
{
listaFile.map((file,index)=>{
return <div key={file.key}><input type="checkbox" value={file.key}
onChange={(e)=>handleCheck(e)}/> {file.key}</div>
})
}
</ul>
<label>File selezionati:</label>
<ul>
{
fileSelezionati.map((file,index)=>{
return <div><input key={file.key} type="checkbox" value={file.key}
checked={true}>{file.key}</input></div> })
}
</ul>

you can do this
<ul>
{
listaFile.map((file,index)=>{
return <div key={file.key}><input type="checkbox" value={file.key}
onChange={(e)=>handleCheck(file.key, e.target.checked)}/> {file.key}</div>
})
}
</ul>
<label>File selezionati:</label>
<ul>
{
fileSelezionati.map((file,index)=>{
return <div><input key={file.key} type="checkbox" value={file.key}
checked={true}>{file.key}</input></div> })
}
</ul>
const [fileSelezionati,setFileSelezionati] = useState([]);
const [listaFile,setListaFile] = useState([]);
function handleCheck(key, checked){
if(checked){
const item = listaFile.find(f => f.key === key)
setListaFile(listaFile.filter(f => f.key !== key));
setFileSelezionati([...fileSelezionati, item]);
}
}

Related

Preselect checkbox if id is present in array angular

I have this checkbox
<div *ngFor="let user of userList">
{{ userList.Name }}
<input type="checkbox" (change)="selectUser($event,user)">
</div>
selectUser(event,user)
{
if (event.target.checked) {
const userDetails = {
userID: user.UserID,
Name:Name ,
};
this.tempLists.push(userDetails);
}
else
{
this.tempLists= this.tempLists.filter(function(obj) {
return obj.userID !== user.UserID;
});
}
}
in this method I'm adding the selected user to the array, but i want that if id is present in the array then when reloading the content where checkbox is present, the checkbox should be selected if that particular id is present in the array.
You need to merge the userList and the tempLists in order to put a property checked on userList and then just add [checked]="user.checked"
The merge part:
userList.map(u =>{
const potentialTempLists = tempLists.find(t => t.UserID === u.UserID)
return potentialTempLists ? {...u, checked: true} : u
});
You can create a function that will check if user is there in the temp list and based on that you can mark checkbox as checked so in you ts file
isChecked(user){
return this.tempLists.some(u=> u.userID==user.UserID);
}
Then on UI user this function to see if user is checked or not
<input type="checkbox" [checked]="isChecked(user)" (change)="selectUser($event,user)">
Working demo

react js Input fields not updating after successful array update

I have a set of a input fields, dynamically generated by an array that are intended to be populated by default with a '?'. Once a user enters a letter into one of the inputs, the onchange event should fire and the array updates successfully, repopulating the inputs with the updated values. As of now, if I provide a value={letter} as an attribute, the inputs populate as expected, but the array that populates the inputs does not update. If I take value={letter} out, the array updates as expected, but the inputs of course, don't populate.
const [letters, setLetters] = useState(workLetters);
function inputChangeHandler(event) {
const incomingLetter = event.target.value;
const nextLetters = [...letters];
letters.forEach((letter, idx) => {
if (letters_rec_of_truth[idx] === incomingLetter) {
nextLetters[idx] = incomingLetter;
}
});
console.log("next letters is now " + nextLetters);
setLetters(nextLetters);
}
useEffect(() => {}, [letters]);
console.log("letters is now " + letters);
// console.log(evt);
return (
<div>
{letters.map((letter, idx) => {
return (
<input
type="text"
key={idx}
value={letter}
onChange={inputChangeHandler}
></input>
);
})}
</div>
);
Why instead of 'value' dont you use 'defaultValue' for the 'input' tag?

React not triggering re-rendering of form inputs after state is updated via onChange

I am trying to build out a verification code page.
If I create an individual state for each input box, and then use the code below, it works appropriately.
<input type="number" value={inputOne} className={styles.codeInput} onChange={e => setInputOne(e.target.value}/>
However, I was trying to consolidate the state for all four of the input boxes, into one state object.
Now, when I type in a number, it moves on to the next input, but it never renders the value. In dev tools, I see the value flash like it updates, but it still stays as "value" and not "value="1"" for example.
However, if I do anything else to my code, like for example, change a p tag's text, then suddenly it updates and the inputs show the correct value.
I'm just trying to figure out what I'm doing wrong here.
Here's my current code.
import { useState } from 'react'
import styles from '../../styles/SASS/login.module.scss'
export default function Verify(params) {
const [verifCode, setVerifCode] = useState(['','','','']);
const inputHandler = (e, index) => {
// get event target value
let value = e.target.value;
// update state
let newState = verifCode;
newState[index] = value;
setVerifCode(newState);
// move focus to next input
if (e.target.nextSibling) {
e.target.nextSibling.focus()
} else {
// if at the last input, remove focus
e.target.blur();
}
}
return (
<div className={styles.verify}>
<p className={styles.title}>Verification</p>
<p className={styles.message}>Please enter the verification code we sent to your email / mobile phone.</p>
<div className={styles.form}>
<input type="number" value={verifCode[0]} className={styles.codeInput} onChange={e => inputHandler(e, 0)}/>
<input type="number" value={verifCode[1]} className={styles.codeInput} onChange={e => inputHandler(e, 1)}/>
<input type="number" value={verifCode[2]} className={styles.codeInput} onChange={e => inputHandler(e, 2)}/>
<input type="number" value={verifCode[3]} className={styles.codeInput} onChange={e => inputHandler(e, 3)}/>
</div>
<div className={styles.footer}>
<button>Verify Code</button>
</div>
</div>
)
};
I believe the problem lies in the following code
// update state
let newState = verifCode;
newState[index] = value;
setVerifCode(newState);
First line of the code just adds a pointer to the value verifCode.
You modify an element in that array, but newState is still the same variable verifCode. Even though the array elements have changed essentially it is still same variable (same reference).
Try something like:
// update state
const newState = [...verifCode]; // create a copy of the old verifCode, creating new array
newState[index] = value; // modify element
setVerifCode(newState); // set the new array to the state

How to check from a list which check boxes have been selected and which are not in protractor using javascript

I am trying to write an end to end test using protractor and i want get the names from a list to check which check boxes have been selected which one's are not.
I can check using isSelected() to check the state of the checkbox but how do i get the list of the names corresponding to it.
This is what i have i want get the label Option 1 and option 2 one by one to see if it is selected or not:
<ul _ngcontent-c8="" class="children" style="">
<li _ngcontent-c8="" class="ng-tns-c8 " ng-reflect-ng-class="[object Object]">
<input _ngcontent-c8="" class="ng-tns-c8" id="all" type="checkbox">
<label _ngcontent-c8="" class="ng-tns-c8" for="all">Option 1</label>
</li>
<li _ngcontent-c8="" class="ng-tns-c8 " ng-reflect-ng-class="[object Object]">
<input _ngcontent-c8="" class="ng-tns-c8" id="all" type="checkbox">
<label _ngcontent-c8="" class="ng-tns-c8" for="all">Option 2</label>
</li>
</ul>
Any help and suggestion will be really appreciated
I have two approaches you can try but have not actually ran either of them myself. They both involve getting all list items in that ul first and both are written using the async/await syntax.
option1
let checkedNames = [];
//iterate over all list items
await element.all(by.xpath('ul[#class="children"]//li')).each(async (li) => {
//if checkbox is selected then get label text and add to array
let chkboxIsSelected = await li.element(by.tagName('input')).isSelected();
if (chkboxIsSelected) {
let lableTxt = await li.element(by.tagName('label')).getText();
//Add lable text to array of labels
checkedNames.push(lableTxt);
};
})
Explanation
element.all(by.xpath('ul[#class="children"]//li')) will return an elementFinder array and there are several methods we can call on element finder arrays, all of them listed here. .each is one of those methods and what it will do is iterate over the element finder array and run a function on each element. It needs to have the element passed into the function in order to run.
The syntax for this would be as follows
eleArray.each(function(elementInArray){
})
We can declare this function using arrow notation and as it is an array of list items we are iterating over we can rename the parameter being passed into the function as 'li' to be more descriptive.
eleArray.each((li) => {
})
Also, as I am using the async/await syntax instead of the promise manager I add the keyword async before all of functions that contain an asynchronous opertation, in your case checking if checkbox is selected in browser and getting text from input field.
option2
let allListItems = await element.all(by.xpath('ul[#class="children"]//li'));
//filter out all of the list items that contain unchecked checkboxes
let itemsWithSelectedChkbox = await allListItems.filter(async li => {
return await li.element(by.tagName('input')).isSelected();
});
//convert the array of list items into an array which contains
let textForAllCheckedBoxes = await itemsWithSelectedChkbox .map(async li => {
return await li.element(by.tagName('label')).getText();
})
console.log(`The test associated with all the checked checkboxes is ${textForAllCheckedBoxes}`);
Hope these are of some use to you but let me know if there issues!

Vue update object based on checkbox checked list of objects?

Some trouble with saving some array that uses a main-array, but is added to another object.
I have a list of distances (array of numbers).
<ul>
<li v-for="(distance, index) in distances">
<a>{{ distance }} km</a>
</li>
</ul>
And the same view I can add some new distances
<input type="number" v-model="newDistance" /><button #click="addDistance(newDistance)">+</button>
This works, the distances are added to the array when added.
After adding the distance to the ul-list, I also want to add the distances to the checkboxes of each Car that is inside an other array.
<article v-for="car in cars">
<div v-for="(distance, index) in distances">
<div #click="updateCar(car, product.distances)">
<input :id="car.slug+index" :name="car.slug" type="checkbox" :checked="checkDistances(surface, car)" />
<label :for="car.slug+index">{{ distance }} km</label>
</div>
</div>
</article>
The working Functions:
checkDistances(distance, car) {
var self = this;
if(typeof car.distances === 'object') {
if(typeof car.distances[self.form.slug] !== 'undefined') {
return (car.distances[self.form.slug].includes(distance))
}
}
return false;
},
And the function to add distances:
addDistance(newDistance) {
this.distances.push(parseInt(newDistance));
},
This is the UpdateCar function
updateCar(car, distances) {
console.log(this.distances);
console.log(distances);
},
Both console logs show the same array. It all returns always ALL items the are in the 'distances' array and not only the selected input fields..
What I want, is that I can update a car when checking a checkbox, so it'll return only the distances that are selected.
It seems like you're just toggling the checkboxes on and off based on the result of checkDistances, but not storing them anywhere. The organization of your example isn't 100% clear to me, but you probably want something along these lines:
// In your template
<input
:id="car.slug+index"
:name="car.slug"
type="checkbox"
:checked="distance in car.distances"
#click="addDistanceToCar(distance, car)" />
// In your methods:
addDistanceToCar(distance, car) {
car.distances.push(distance)
}

Categories