Remove query parameter - javascript

I have a complex multi-select filter page so I'm grouping filters like this http://localhost:3000/search?id[]=101404&id[]=7267261. I'm using URLSearchParams() to manage my URLs.
The only thing that is not working is removing a parameter once it has been unchecked. I tried using the URLSearchParams.delete(), but it only accepts a single parameter, name. If I pass id[], it removes ALL id[]'s, not just the one I want to be deleted.
EDIT: based on recommendations, I have this new code (see old code below). Hoping someone has a far more elegant solution.
setQueryParams = (param = null, value = null, category = null) => {
....
// parameter exists but value is false
} else if (param && !value) {
// find all values for category and filter out unchecked value
const values = params.getAll(`${category}[]`).filter(category => category !== param)
// remove entire category from URLSearchParams
params.delete(`${category}[]`)
// loop over filtered list and append them BACK to URLSearchParams
values.forEach((value) => {
params.append(`${category}[]`, value)
});
}
this.setState({
query: params.toString()
});
}
The only other way I can think of is to write some Regexp, which I wasn't able to get it to work anyway. My params are encoded, so shouldn't something like this work? I can't even get this to work in console...
"id%5B%5D=101404&id%5B%5D=7267261".replace(/\%5\%D/,'')
"id%5B%5D=101404&id%5B%5D=7267261".replace(/%5%D/,'')
"id%5B%5D=101404&id%5B%5D=7267261".replace(/\[\]/,'')
None of these work. Here is my code generating the query parameters.
setQueryParams = (param = null, value = null, category = null) => {
const query = this.state.query;
// get current location
const location = this.props.location.search;
// Set params based on whether component mount or filter change
const params = param ? new URLSearchParams(query) : new URLSearchParams(location);
// value must be equal to true
if (param && value) {
params.append(`${category}[]`, param);
// parameter exists but value is false
} else if (param && !value) {
params.delete(category);
}
this.setState({
query: params.toString()
});
}

What if you use the getAll('id[]'), iterate over the results and append() the ones you want.
Although it's not that elegant of a solution, I think it's still better than the regex approach.

setQueryParams = (param = null, value = null, category = null) => {
....
// parameter exists but value is false
} else if (param && !value) {
// find all values for category and filter out unchecked value
const values = params.getAll(`${category}[]`).filter(category => category !== param)
// remove entire category from URLSearchParams
params.delete(`${category}[]`)
// loop over filtered list and append them BACK to URLSearchParams
values.forEach((value) => {
params.append(`${category}[]`, value)
});
}
this.setState({
query: params.toString()
});
}

Related

Checking whether information is in database

I am trying to check whether a specific productID and orderID is in my database.
Currently, I am calling and fetching the data from my database like so.
const { data } = useFetchCollection("returns");
const filteredReturns = data.filter((mapper) => mapper.userID === userID);
const idReturns = filteredReturns.flatMap((mapper) => {
const getOrderID = mapper.orderID;
const getProductID = mapper.productID;
return [getOrderID, getProductID];
});
The data is being called and I am getting this array back:
['xxy6mkDDIhXQbUcol1Vh', '6RpJmOYLcGOkyAW4ElP9', 'JIzCbmOqp5wCGz7pHGSL', '6RpJmOYLcGOkyAW4ElP9']
I also have the orderID and productID from the user, these pieces of data will be in the database if a user has submitted a return and not in the database if the user has not submitted a return. So in other words it may or may not be in the database.
The orderID and the productID which is specific to the user is in this format for example,
userDetails[0].id = 6RpJmOYLcGOkyAW4ElP9
id = JIzCbmOqp5wCGz7pHGSL
I now want to check whether this data is in the database.
const mapData = idReturns.map((mapper) => {
if(mapper.orderID === userDetails[0].id && mapper.productID === id){
return true
}else {
return false
}
});
I have been using the function above but it doesn't seem to work. It doesn't say true or false properly. Notably, it only says true, false rather than definitively just true true.
I think my approach with my function is poor. I may even be making a mistake by doing this,
return [getOrderID, getProductID]~
but I am open to suggestions and advice.
Thanks in advance!
use findIndex() instead of map()
if(idReturns.findIndex((mapper)=>mapper.orderID === userDetails[0].id && mapper.productID === id) !=-1) {
return true
}else{
return false
}

While updating data for one field shows undefined for other in an object

In a Grid, certain records are populated, which also includes two input fields one for date and other for text. When changed data for date, text data gets undefined and when text is changed date is undefined which can be observed in console. After changing data I need to save it in the function. Please refer to the code below:
Following is the updateGrid function which I'm getting from Grid
<Grid
OnTextCallback={updateGrid}
DateCallBack={updateGrid}
/>
const updateGrid = (data) => {
if (Array.isArray(newDataHere) && newDataHere?.length > 0) {
// newDataHere is an array of data
const tempData = newDataHere;
tempData.map((x) => {
if (data.id === x.id) {
x.name = data.textVal;
}
if (data.id === x.id) {
x.Establish = data.dateVal;
}
});
setDataAll(tempData);
}
console.log("tempdataNew", dataAll);
};
As seen from above code, both text and date has similar id which is received from Grid, but, when changed one field shows undefined for another field. How can this be tackled?
Please refer to codesandbox --> https://codesandbox.io/s/jovial-aryabhata-95o2sy?file=/src/Table.js
Your Grid component only returns dateVal or textVal with each kind of value change, so you cannot change them both together.
For the fix, you can add a condition to check your value availabilities from each value change
const updateGrid = (data) => {
if (Array.isArray(newDataHere) && newDataHere?.length > 0) {
const tempData = newDataHere;
tempData.forEach((x) => {
if (data.id === x.id) {
//if textVal is available, we will update
if (data.textVal) {
x.name = data.textVal;
}
//if dateVal is available, we will update
if (data.dateVal) {
x.Establish = data.dateVal;
}
}
});
setDataAll(tempData);
}
console.log("tempdataNew", dataAll);
};
The sandbox link

Value is not changing in real time -- VueJS

I am using a JS class, I have following code:
class Field {
public Value = null;
public Items = [];
public UniqueKey = null;
public getItems() {
let items = [...this.Items];
items = items.filter((item) => {
if (item.VisibleIf) {
const matched = item.VisibleIf.match(/\$\[input:(.*?)\]/g);
if (matched?.length) {
const srv = Service.getInstance();
for (let match of matched) {
match = match.slice(8, -1);
if (srv.Fields?.length) {
let found = srv.Fields.find((x) => x.UniqueKey === match);
if (found) {
item.VisibleIf = item.VisibleIf.replace(
`$[input:${match}]`,
found.Value ?? ''
);
return JSON.parse('' + eval(item.VisibleIf));
}
}
}
}
}
return true;
});
return items;
}
public getInputTitle() {
let title = this.Title;
const matched = title.match(/\$\[input:(.*?)\]/g);
if (matched?.length && title) {
const srv = Service.getInstance();
for (let match of matched) {
match = match.slice(8, -1);
if (srv.Fields?.length) {
let found = srv.Fields.find((x) => x.UniqueKey === match);
if (found) {
title = title.replace(`$[input:${match}]`, found.Value ?? '');
}
}
}
}
return title;
}
}
Now I have a Vue component:
<div v-for="Field in Fields" :key="Field.UniqueKey">
<v-select
v-if="Field.Type == 'Select'"
:label="Field.getInputTitle()"
v-model="Field.Value"
:items="Field.getItems()"
item-text="Value"
item-value="Id"
/>
<v-input
v-else-if="Field.Type == 'Input'"
v-model="Field.Value"
:label="Field.getInputTitle()"
/>
</div>
// JS
const srv = Service.getInstance();
Fields = srv.getFields(); // <- API call will be there.
So basically, data comes from an API, having Title as Input $[input:uniqueKey], in a component I am looping over the data and generating the fields. See getInputTitle function in Field class, it works very well. All the fields which are dependent on the $[input:uniqueKey] are changing when I start typing into that field on which other fields are dependent.
Now I have pretty much same concept in the getItems function, so basically, what I want to do is whenever I type into a field and that field exists in the VisibleIf on the Items, the VisibleIf will be like '$[input:uniqueKey] < 1', or any other valid JavaScript expression which can be solved by eval function. But the getItems function is called only 1st time when page gets loaded, on the other hand the getInputTitle function which is pretty much same, gets called every time when I type into the field.
I tried to explain at my best, I will provide any necessary information if needed.
Any solution will be appreciated. Thanks.
You are updating the Object itself in here:
item.VisibleIf = item.VisibleIf.replace( `$[input:${match}]`, found.Value ?? '' );
Even though you tried to copy the array, but you have done shallow copy of the object in here: let items = [...this.Config.Items];
I suggest the following solution:
const visibleIf = item.VisibleIf.replace(
`$[input:${match}]`,
found.Value ?? ''
);
const val = '' + helpers.evalExp('' + visibleIf);
if (helpers.isJSON(val)) {
return JSON.parse(val);
}
Means instead of changing the VisibleIf object, just store it into the variable and just use that.
I hope that it will fix your issue. Let me know if it works.

How can I check whether an item exists in localstorage or not using pure javascript

I have a project on pure javascript,and I was working on saving items to localstorage. I only need to save id, name and image of the item i am saving.
My major problem , however is i do not want save duplicate .Therefore before i save i must check whether the exists or not.
I have so far tried several approaches but all seems not to work.Below is my code snippets.
I am able to save item to localstorage with no problems, infact i can save and delete items from localstorage correctly.
const cart_DB = new cartDB();
if( cart_DB.isAddedToCart(cartInfo.id) === false) {
// save item to database
}else {
alert('item already in cart');
return false;
}
class cartDB {
/// save cart into localstorage ////
saveIntoDB(cart) {
const carts = this.getFromDB();
carts.push(cart);
// add the new array into localstorage
localStorage.setItem('carts', JSON.stringify(carts));
}
/// save cart into localstorage ///
/// return carts from storage ///
getFromDB() {
let carts;
// check from local storage
if (localStorage.getItem('carts') === null) {
carts = [];
} else {
carts = JSON.parse(localStorage.getItem('carts'))
}
return carts;
}
/// carts from storage ends ///
/// check if item already exists in database ////////
isAddedToCart(id) {
if (localStorage.getItem(id) === null
||localStorage.getItem(id).length === 0) {
return false;
}else {
return true;
}
}
//// checking items ends here ///////
}
What i want is to check whether the item exists or not before adding another item.
Assuming that you store items in array you can use below function to check if item already exists:
function checkIfItemExists (id) {
const items = localStorage.getItem('carts')
let itemExists = false
if (items) {
const itemsData = JSON.parse(items)
// check if item with given id exists in local storage data
itemExists = itemsData.find(item => item.id === id)
}
return itemExists
}
If your goal is to find out if there's a duplicate, Array.some() would be the best function you are looking for. Implement it to your function like this.
isAddedToCart(id) {
const carts = localStorage.getItem('carts');
return carts.some(cart => cart.id == id);
}
Array.some() Definition and Usage
The some() method checks if any of the elements in an array pass a
test (provided as a function).
The some() method executes the function once for each element present
in the array:
If it finds an array element where the function returns a true value, some() returns true (and does not check the remaining
values)
Otherwise it returns false

ComboBox typeAhead works but valueField is null under certain behavioral conditions

Requesting a sanity check here please...
ExtJS 4.2 comboBox Typeahead works but having issues retrieving the valueField under the following conditions:-
1) If a user types a value and then instead of hitting enter or clicking on the select combo list, they click elsewhere then the valueField is empty but the selected value is present.
2) Assuming that the combobox item was selected correctly, If I enter an additional character and then backspace that character, the combo box can no longer find the valueField..its almost like it has reset itself.
Fiddle example
https://fiddle.sencha.com/#fiddle/je1
How to reproduce
If you enter Maggie in the combo box, you will see the valueField ID in the console window, if you append a character and then backspace the character, the ID in the console window is null
(You will need to open the console window to see the output)
forceSelection does not resolve this issue as I have a template and it will not accept an entry in the combobox that is not part of the store, and I need to use sumID for my valueField as I need to retrieve and pass that value to the server.
Thank you everyone, awesome to have such a great community!!
I was able to get around this by using forceSelection and overriding the setValue thus allowing template items not in the store but in the combo to be selected via forceSelection. From playing around with the combobox, IMO, for a good look and feel, forceSelection is the way to go.
Here is my override, refer to statement //start of override
This was a quick fix, I will refine statement when I am back in the office, below I am pasting the solution from memory, you get the idea.
setValue: function(value, doSelect) {
var me = this,
valueNotFoundText = me.valueNotFoundText,
inputEl = me.inputEl,
i, len, record,
dataObj,
matchedRecords = [],
displayTplData = [],
processedValue = [];
if (me.store.loading) {
// Called while the Store is loading. Ensure it is processed by the onLoad method.
me.value = value;
me.setHiddenValue(me.value);
return me;
}
// This method processes multi-values, so ensure value is an array.
value = Ext.Array.from(value);
// Loop through values, matching each from the Store, and collecting matched records
for (i = 0, len = value.length; i < len; i++) {
record = value[i];
if (!record || !record.isModel) {
record = me.findRecordByValue(record);
}
// record found, select it.
if (record) {
matchedRecords.push(record);
displayTplData.push(record.data);
processedValue.push(record.get(me.valueField));
}
// record was not found, this could happen because
// store is not loaded or they set a value not in the store
else {
//start of override
// 'Select All Names' is the template item that was added // to the combo box, it looks like an entry from the store
// but it is not in the store
if (me.forceSelection && me.getDisplayValue() === 'Select All Names'){
processedValue.push(value[i]);
dataObj = {};
dataObj[me.displayField] = value[i];
displayTplData.push(dataObj);
}
//end of override
if (!me.forceSelection) {
processedValue.push(value[i]);
dataObj = {};
dataObj[me.displayField] = value[i];
displayTplData.push(dataObj);
// TODO: Add config to create new records on selection of a value that has no match in the Store
}
// Else, if valueNotFoundText is defined, display it, otherwise display nothing for this value
else if (Ext.isDefined(valueNotFoundText)) {
displayTplData.push(valueNotFoundText);
}
}
}
// Set the value of this field. If we are multiselecting, then that is an array.
me.setHiddenValue(processedValue);
me.value = me.multiSelect ? processedValue : processedValue[0];
if (!Ext.isDefined(me.value)) {
me.value = null;
}
me.displayTplData = displayTplData; //store for getDisplayValue method
me.lastSelection = me.valueModels = matchedRecords;
if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
inputEl.removeCls(me.emptyCls);
}
// Calculate raw value from the collection of Model data
me.setRawValue(me.getDisplayValue());
me.checkChange();
if (doSelect !== false) {
me.syncSelection();
}
me.applyEmptyText();
return me;
},
Look at the sources of Combobox and try override this method as follows
doLocalQuery: function(queryPlan) {
var me = this,
queryString = queryPlan.query;
if (!me.queryFilter) {
me.queryFilter = new Ext.util.Filter({
id: me.id + '-query-filter',
anyMatch: me.anyMatch,
caseSensitive: me.caseSensitive,
root: 'data',
property: me.displayField
});
me.store.addFilter(me.queryFilter, false);
}
if (queryString || !queryPlan.forceAll) {
me.queryFilter.disabled = false;
me.queryFilter.setValue(me.enableRegEx ? new RegExp(queryString) : queryString);
}
else {
me.queryFilter.disabled = true;
}
me.store.filter();
if (me.store.getCount()) {
if (me.rawValue === me.lastSelection[0].get(me.displayField)){
me.setValue(me.lastSelection);
} else {
if(me.store.getCount() === 1){
me.setValue(me.store.first());
}
me.expand();
}
} else {
me.collapse();
}
me.afterQuery(queryPlan);
},

Categories

Resources