Using index in css selector - javascript

I'm using testcafe for automation and have dynamic css locator like this
this.infoQCLog = (index , name , date , subTitle , desc , index) => Selector('*[data-element-name = "content-checklog"]').nth(`${index}`).child('div').withText(`${name}`).nextSibling('div').withText(`${date}`).nextSibling('div').withText(`${subTitle}`).nextSibling('div').withText(`${desc}`)
but have issue that The "index" argument (string) is not of expected type (number). Have any solution that can resolved it ?

Please try this code:
this.infoQCLog = (index, name, date, subTitle, desc) => {
return Selector('*[data-element-name="content-checklog"]')
.nth(Number(index))
.child('div')
.withText(`${name}`)
.nextSibling('div')
.withText(`${date}`)
.nextSibling('div')
.withText(`${subTitle}`)
.nextSibling('div')
.withText(`${desc}`);
};

Related

print value to screen according to condition

I am getting the "address" value from the backend. However, the incoming value is all uppercase. I just want the first letters to be uppercase. I achieved this. But I get an error when "address" value does not come.
const upperCaseFirstLetter = (string) =>
`${string.slice(0, 1).toUpperCase()}${string.slice(1)}`;
const lowerCaseAllWordsExceptFirstLetters = (string) =>
string.replaceAll(/\S*/g, (word) => `${word.slice(0, 1)}${word.slice(1).toLowerCase()}`
);
let address = '';
address = upperCaseFirstLetter(lowerCaseAllWordsExceptFirstLetters(props.policy.assets.address));
html
<div className="policycard__subinfo">
{props.policy.assets.address ? (t('policy.policy-cards.address') + address) : null}
</div>
The error in the console is as follows; Cannot read properties of undefined (reading 'replaceAll').
There is probably a better way, but any time I run into an error like that I like to just give it a default value:
const lowerCaseAllWordsExceptFirstLetters = (string) => {
return (string || '').replaceAll(/\S*/g, (word) => `${word.slice(0, 1)}${word.slice(1).toLowerCase()}`
}
so that if string is undefined, it instead is treated as an empty string and you avoid the error.

Remove a URL search parameter when there is duplicate names?

I am trying to manipulate my URL using URLSearchParams. However URLSearchParams.delete() expects the name of the param. If I have params with the same name, (from what I've tested in chrome) It will delete all params with that name. Is there a way to delete by both name and value?
My query looks something like this:
?color[]=Black&color[]=Green&material[]=Steel
So when I call .delete("color[]") it will remove both color[]= params, but what if I want to only remove a specific one?
The reason for the duplicate names is the backend (PHP) is leveraging this functionallity to auto parse the parameters into arrays...which requires the syntax above.
Big picture is- I'm trying to add/remove "filters" from this array-to-be. Also, some filter categories could have matching values so I don't want remove by value either. I am open to considering an entirely new approach...just trying to do it in the least hacky way.
-- Edit --
For any Laravel users, I recommend not using the index-less syntax. Just use color[0]=, color[1]= etc. I didn't realize laravel supports both syntaxes.
To remove a specific key/value pair, loop over the entries, filter out the unwanted one(s) and create a new URLSearchParams:
function deleteParamsEntry(params, key, value) {
const newEntries = Array.from(params.entries()).filter(
([k, v]) => !(k === key && v === value)
);
return new URLSearchParams(newEntries);
}
const query = "?color[]=Black&color[]=Green&material[]=Steel";
const params = new URLSearchParams(query);
const newParams = deleteParamsEntry(params, "color[]", "Green");
console.log(newParams.toString());
Try this approach:
const deleteURLParamsByNameAndValue = (urlString, paramName, paramValue) => {
const url = new URL(urlString)
const params = url.searchParams
const newParamArray = []
for (var kvPair of params.entries()) {
const k = kvPair[0]
const v = kvPair[1]
if (k!==paramName || v!==paramValue) {
newParamArray.push(kvPair)
}
}
const newSearch = new URLSearchParams(newParamArray)
return decodeURI(`${url.origin}${url.pathname}?${newSearch}`)
}
const urlString = 'https://example.com/path1/path2?color[]=Black&color[]=Green&material[]=Steel'
deleteURLParamsByNameAndValue(urlString,'color[]','Black')
// returns 'https://example.com/path1/path2?color[]=Green&material[]=Steel'

React js update object value in an array with n number of input data useState

So I'm creating a todolist with react js, the website allow me to add multiple task in a single instance, which mean that i can add any number of input field and fill it with data and save it. My method is to use a pre-defined json object, whenever i add an input field, useEffect will handle it by pushing the pre-defined json object into an array and useState will set the newly array.
This my code for adding a input field or a child:
//hook for the input field/children count
const [taskCount , setTaskCount] = useState(1);
//hook for all the input data, the initial data is an empty array
//whenever the taskCount increases, it will set a new array
const [test , setTest] = useState([]);
//pre-defined json object schema
const schema =
{
id : 0,
choice : '',
questName : '',
location : '',
time : '',
linkedQuestB : '',
linkedQuestA : '',
status : [
{id : 'not_started' , label : 'not_started' , checked : false},
{id : 'in_progress' , label : 'in_progress' , checked : false},
{id : 'done' , label : 'done' , checked : false},
],
}
//function onClick for adding input
//whenever a new input is created
//temp id is increment for input value onChange
function addField ()
{
let initilaTest = test ;
const temp = {...schema};
temp.id = taskCount;
initilaTest.push(temp);
setTest(initilaTest);
}
useEffect(() => {
addField();
console.log(test)
} , [taskCount])
const someExampleFunction ()
{
return (
<img
src = {plus}
alt = {'exist non'}
onClick = {()=> setTaskCount(taskCount+ 1)}
/>
<exampleFunctionforInput >
{[...Array(taskCount)].map((value , index)=>{ return (<TodoFieldSet id ={index}
key = {index}
update = {updateval} />)})}
</exampleFunctionforInput >)}
So to change the value in each respective input, i use onChange method. The method for handling the onChange method is as follow, whenever the input value change, onChange will fire the update function, which takes the index as param id and a param of event.target to change the respective input value with looping the key of the object and matching the e.target.id and finally change the state of test. It does worked, but obviously whenever the number of input field increases, typing in the input field get slower, because there is a ton of object in the array to loop through and find respective data. So is there a better ways of doin it.
Code for input field components :
const inputProps =
[
{id : 'questName' , name : 'Quest Name',type :'text' , },
{id : 'time' , name : 'Time',type :'text' ,},
{id : 'linkedQuestB' , name : 'Linked Quest Before',type : 'text',},
{id : 'linkedQuestA' , name : 'Linked Quest After',type : 'text',},
{id : 'location' , name : 'location',type : 'text',},
]
//handling the onChange
const updateval = (index , target ) =>
{
let temp = [...test];
for(let key in temp[index])
{
if(key === target.id )
{
temp[index][key] = target.value;
}
}
setTest(temp);
}
function exampleFunctionforInput ({id , update})
{
return (
{inputProps && inputProps.map((value , index)=>
{
return (
<TodoInWrapper key = {index} id = {value.name + id}>
<label htmlFor = {value.id}>{value.name}</label>
<input
id = {value.id}
type = {value.type}
onChange = {e => update(id , e.target)}
/>
</TodoInWrapper>)
})};)
}
Don't mind the all the React Components tag, they are styled components.
You're looping through all elements to find the element then you update it, if you want to avoid that, you can use a key-value map, where that will enhance performance from O(n) to O(1)
Other possible optimisations could be done, which I believe will make difference:
Eliminate mutations
Making functions pure (they have side effects)
Name of components should start with Capital letter in React
To pass more predictable keys to TodoInWrapper
Use useCallback for functions within the Component
I couldn't give example code because the provided code is hard to be used as a reference

Filtering Data By Full Name React

Hi I am Trying to filter my Data By Full Name, my API takes in a first and last name and I am returning it as:
const filteredStudents = students.filter( student => {
return (student.firstName.toLowerCase().includes(search.toLowerCase()) + student.lastName.toLowerCase().includes(search.toLowerCase()));
})
which only shows a result when typing a first or last name is there a way to handle a condition for when you type in the whole name?
For Example, "Bill Gates"
You can concatenate the names first, then check if the search term is contained.
const filteredStudents = students.filter((student) => {
return `${student.firstName} ${student.lastName}`
.toLowerCase()
.includes(search.toLowerCase());
});

ngx dropdown list get selected values

I am trying to use ngx dropdown list like this:
<ngx-dropdown-list [items]="categoryItems" id="categoriesofdata" [multiSelection]="true"
[placeHolder]="'Select categories'"></ngx-dropdown-list>
And I am getting all selected values like:
get selectedCategories() {
const items = this.categoryItems.filter((item: any) => item.selected);
return items.length ? JSON.stringify(items.map(item => ({
value: item.value
}))) : '';
}
and output looks like:
[{"value":"Surname"},{"value":"Address"}]
I want to get only for example Surname instead of value and Surname.
[0].value
How Can I do this?
Should I use for loop or is better option?
I think you're almost there, in fact you're doing a little too much. Your map function should just return the value you are interested in rather than creating a new structure.
get selectedCategories() {
const items = this.categoryItems.filter((item: any) => item.selected);
return items.length ? JSON.stringify(items.map(item => item.value)) : '';
}
Edit:
And as a personal preference, I would refactor to something like this:
get selectedCategories() {
if (!this.categoryItems.length) {
return '';
}
const surnames = this.categoryItems
.filter(item => item.selected)
.map(item => item.value);
return JSON.stringify(surnames);
}
I prefer to get out of a function early in the case where no further processing is required. And I would return the result of chained filter and map functions into a new surnames variable. The named variable signals the intention of the code, and keeps the array logic together.
This is just my preference though. Your code was almost there functionally.

Categories

Resources