I have a function which executes when the dropdown has a value of add or remove it will execute accordingly. However on the first render after I click the button it shows as 'added data'null. When I do it again it works. What would be the best way to handle this?
Here is my code:
Since I can't see any of the other code and there is no sandbox, I can only help you fix the issue of checking for null, however if we could see the component this function is in I could answer a lot more, however here is how you can check for null
const addtoproduction = () => {
let databaseChanges = unitTestsData.map(tests => {
return {
"unit_test_id": tests.unit_test_template_id,
"databases": tests.databases
}
})
setAddRemoveDatabaseChanges(databaseChanges)
if(AddRemoveDatabaseMode !== null && AddRemoveDatabaseMode === 'ADD'){
console.log('added data', AddRemoveDatabaseChanges);
} else if (AddRemoveDatabaseMode !== null && AddRemoveDatabaseMode === 'REMOVE') {
console.log('removed data', AddRemoveDatabaseChanges )
}
}
Related
I have a list in angular, an array. OnInit it gets filled from the right corresponding database items. I created a form above it. When you enter something in the form, it acts like a filter. This works, the first time. When you erase something from the form and enter something else, the list should be refreshed and afterwards filtered based on the new input. This doesn't happen. I put the formula that happens on onInit in my function to refill the list.
Below you can find my function (I left the console logs in) and a screenshot of the problem. First I look for a user (joeri.boons#hi10.be) which returns three results. Than I erase the user and look based on a month 7. The screen returns a new unfilterd list while in the console it still holds the list of 3 x user joeri.boons#hi10.be. So there is an inconsistency to. If you look at screen result you would think of a filter problem, the console points at a refreshproblem.
if more code is required let me know.
updateWithFilter(): void {
console.log("function update filter reached")
console.log(this.listadapted);
if(this.listadapted == true){
// this.timesheetsHandled = {} as TimeSheet[];
this.getHandledSheet();
console.log("getHandledSheet executed")
}
if(this.filterUsername.trim() && !this.filterYear && !this.filterMonth){
console.log("option 1 reached")
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
this.timesheetsHandled = this.timesheetsHandled.filter(sheet => sheet.username == this.filterUsername);
this.listadapted = true;
} else if(!this.filterUsername.trim() && !this.filterYear && this.filterMonth){
console.log("option 2 reached");
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
console.log("before filter");
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
this.timesheetsHandled = this.timesheetsHandled.filter(sheet => sheet.month == this.filterMonth);
console.log("after filter");
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
// console.log(this.timesheetsHandled.filter(sheet => sheet.month == this.filterMonth));
this.listadapted = true;
} else if .. more options
}
ngOnInit(): void {
this.getHandledSheet();
}
getHandledSheet(): void {
this.timesheetService.getAllTimesheets().subscribe({next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => sheet.status == 'HANDLED') }}) ;
}
My guess would be that this is caused by loading data in ngOnInit. As the documentation (https://angular.io/api/core/OnInit) states : [...] It is invoked only once when the directive is instantiated.
I suspect that you create one instance and re-use it and the ngOnInit method does not get called again.
UPDATE:
The issue is that the call to this.getHandledSheet(); does a call to .. .subscribe({next: .. which is delayed and the rest of the function is executed first.
So the actual code after next: is only executed after the timeSheetService is done loading the data.
So either you apply the filter in the
{next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => sheet.status == 'HANDLED') }}
block after filtering for 'HANDLED' or you'll try to await in the update function.
Create two variables, one that will always remain unfiltered, then another that will be filtered.
The problem will be that the original list is filtered, hence you are losing the original data after filtering!
timesheetHandled: TimeSheet[];
timesheetHandledOriginal: TimeSheet[];
updateWithFilter(): void {
console.log('function update filter reached');
console.log(this.listadapted);
if (this.listadapted == true) {
// this.timesheetsHandled = {} as TimeSheet[];
this.getHandledSheet();
console.log('getHandledSheet executed');
}
if (this.filterUsername.trim() && !this.filterYear && !this.filterMonth) {
console.log('option 1 reached');
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
this.timesheetsHandled = this.timesheetHandledOriginal.filter(
sheet => sheet.username == this.filterUsername
);
this.listadapted = true;
} else if (!this.filterUsername.trim() && !this.filterYear && this.filterMonth) {
console.log('option 2 reached');
console.log(this.filterUsername.trim());
console.log(this.filterYear);
console.log(this.filterMonth);
console.log('before filter');
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
this.timesheetsHandled = this.timesheetHandledOriginal.filter(
sheet => sheet.month == this.filterMonth
);
console.log('after filter');
this.timesheetsHandled.forEach(sheet => console.log(sheet.username));
// console.log(this.timesheetsHandled.filter(sheet => sheet.month == this.filterMonth));
this.listadapted = true;
}
// else if .. more options
}
ngOnInit(): void {
this.getHandledSheet();
}
getHandledSheet(): void {
this.timesheetService.getAllTimesheets().subscribe({
next: (response: TimeSheet[]) => {
this.timesheetsHandled = response.filter(sheet => sheet.status == 'HANDLED');
this.timesheetHandledOriginal = JSON.parse(JSON.stringify(this.timesheetsHandled));
},
});
}
I wants to prevent addition of duplicate items to cart. I have tried the code below but it's working only for single item, when there are multiple items in the cart the duplicate items are allowed to add in to the cart. Here is my code
addToCart = (id) => {
let item = this.getItem(id);
if ([...this.state.cart]) {
[...this.state.cart].map((i) => {
if (i.product_name == item.product_name) {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
});
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
console.log(this.state.cart);
};
You need to use map only to check if the item already exists, and then either add it or alert that the item is repeated.
One way of doing it would be like this:
existing = [...this.state.cart].map((i) => {
if (i.product_name == item.product_name) {
return i;
}
});
if (existing) {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
Explanation
map function executes the code for each of the items in the collection, which means the moment it finds an item in the cart different from the item selected, it will add the item selected.
So let's say your cart has [apple, orange] and you want to add apple again. When the map code executes it first looks like this:
if ("apple" == "apple") {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, apple]));
}
It doesn't add the item because it already exists... but then it executes a second time, and it looks like this:
if ("orange" == "apple") {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, apple]));
}
It gets added because the second item is different.
What the new code does is that it returns a value only if the item exists and, after looping throuhght all the items in the cart, it checks that value and adds the item if it is nothing.
An item should be added to the cart, if the latter doesn't contain it already.
To check if an Array contains an object, that fulfills a certain condition use the some method, as said by #Isaac Batista.
On the other hand, when you want to update state, by using it's previous value, you should use the callback argument of setState.
See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
this.setState((state)=>{
// if cart already contains item
if(state.cart.some(itm=>itm.product_name == item.product_name)) {
return {}; // do not update state
} else {
return {cart: state.cart.concat(item)}; // add item to cart
}
}
You can use filter method to check whether the item is already available or not. With this you can also avoid the nested if condition also.
addToCart = (id) => {
let item = this.getItem(id);
let checkCart = [...this.state.cart].filter((i) => {
return i.product_name == item.product_name;
});
if (checkCart.length !== 0) {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
console.log(this.state.cart);
};
Here is a functional exemple, but note some points:
You are mutating state, and you should not do it, as it is explained here. So, you should just call setState passing the new value via argument, like this: this.setState(newValue).
A map is used to create a new array, the correct function to find out if some element passes a rule is some. This will allow you to check if some product inside cart is the clicked product.
// quick example
[1,2,3,4].some(number => number === 2) // true
[1,2,3,4].some(number => number === 5) // false
Finally, i would do something like this
const { cart } = this.state;
const product = this.getItem(id);
// returns true if there is any product with the same id
const isProductInCart = cart.some((item) => item.id === product.id);
if (isProductInCart) {
alert("Product already in cart");
} else {
this.setState({
cart: [...cart, product]
});
}
when the search value is changed, the state does not change, although when the search value is reduced, the changes occur instantly
this is one code in order*
if(prop.props.statePokemon){
prop.props.setStatePokemon(false)
why the given value does not change:
setPokemon(saveDataPokemon) // the value does not change
but all other logs are going fine:
let rangePokemonFromAttack:(IPokemon | undefined | any)[] = allPokemon.data.map((pokemon: IPokemon) => {
if(prop.props.rangeAttack.rangeAttackFrom <= pokemon.stats[1].base_stat && pokemon.stats[1].base_stat <= prop.props.rangeAttack.rangeAttackTo){
return pokemon
}
}).filter((pokemon: IPokemon | undefined) => {
return pokemon !== undefined
})
console.log(allPokemon,'all',
saveDataPokemon, 'save',
rangePokemonFromAttack ,'range')
if(typeof rangePokemonFromAttack[0] !== 'undefined'){
setPokemon(saveDataPokemon)
setPokemon({data: rangePokemonFromAttack})
}else{
setPokemon(saveDataPokemon)
}
}
prop.props.rangeAttack.rangeAttackFrom = 0
prop.props.rangeAttack.rangeAttackTo = 400
}
The state variables doesn't change like that you need to use setState() function for this purpose, which in turn calls the render again. For more info Google setState or visit this link https://reactjs.org/docs/react-component.html In this docs search setState function
I made a mistake and caused another state
prop.props.setStatePokemon(false)
let rangePokemonFromAttack:IPokemon[] = saveDataPokemon.data.filter((pokemon: IPokemon) => {
if(prop.props.rangeAttack.rangeAttackFrom <= pokemon.stats[1].base_stat
&& pokemon.stats[1].base_stat
<= prop.props.rangeAttack.rangeAttackTo){
return pokemon
}
})
if(typeof rangePokemonFromAttack[0] !== 'undefined'){
setPokemon({data: rangePokemonFromAttack})
}else{
setPokemon(saveDataPokemon)
}
I have a problem changing a data parameter in my component file:
this.commandList.ListesCommandesATransmettre.forEach(data => {
this.catalogs.forEach(catalog => {
if (catalog.Libelle === data.Catalogue) {
if (catalog.selected === false) {
console.log(data.isSelected)
data.isSelected = false;
console.log(data.isSelected)
console.log(data);
}
}
})
});
This code displays:
true
false
But the value of isSelected in console.log(data) is still true. So, why is the result false?
Try this if it's a loop problem with the callback
for (let data of this.commandList.ListesCommandesATransmettre) {
for (let catalog of this.catalogs) {
if (catalog.Libelle === data.Catalogue) {
if (catalog.selected === false) {
console.log(data.isSelected)
data.isSelected = false;
console.log(data.isSelected)
console.log(data);
}
}
}
}
I cant understand logic of your code. What happen if this.catalogs has many catalogs that meet the condition? isSelected will be setted many times in false.
Maybe this works (if I understand your logic):
this.commandList.ListesCommandesATransmettre = this.commandList.ListesCommandesATransmettre.map(data => {
const mutateData = Object.assign({}, data);
// If condition math, then isSelected set in false. Else, isSelected keep the his value
mutateData.isSelected =
this.catalogs.some(catalog => catalog.Libelle === data.Catalogue && !catalog.selected) ? false : mutateData.isSelected;
return mutateData;
})
Try this code to test if it is updating correctly. the loop will tell which are true/false and you can see if that is the case in the updated data.
this.commandList.ListesCommandesATransmettre.forEach((data, index) => {
this.catalogs.forEach(catalog => {
if (catalog.Libelle === data.Catalogue) {
if (catalog.selected === false) {
data.isSelected = false;
}
console.log(index + 'is selected: ' + data.isSelected)
}
})
});
console.log(this.commandlist);
Something I have noticed is that web browsers will only keep the the 'most current' reference of an object in memory. So after a loop has ended, the 'most current' reference is the last one to fire. So you may be looking at your last object and not the one you are trying to test. If someone else knows more, or has a reference to what is actually happening, please edit this post.
I'm trying to make an input form that will check if the data exists in firebase database, below is the code that I used to check the data :
if(element.validation.codeunique) {
function checkCode(inputcode) {
firebaseUsers.orderByChild('code')
.equalTo(inputcode).once('value')
.then( snapshot => {
let thecode = null;
if(snapshot.val()){
thecode = false;
} else {
thecode = true;
}
console.log(thecode)
})
}
let checkcode = null;
checkcode = checkCode(element.value);
console.log(checkcode)
const valid = checkcode;
const message = `${!valid ? 'Code Exists':''}`;
error = !valid ? [valid,message] : error
}
in database i have a data :
users
-L3ZeHOI7XOmP9xhPkwX
-code:"DEM"
when I entered data DEM at the form :
console.log(thecode) result is false (which is the result that i want)
and when i entered another data ASD at the form :
console.log(thecode) result is true(which is the result that i want)
so the firebaseUsers actually is giving me the feedback/data that I want, but when I tried to get the data at valid with true/false,
this is the code that I originally used:
if(element.validation.codeunique) {
function checkCode(inputcode) {
firebaseUsers.orderByChild('code')
.equalTo(inputcode).once('value')
.then( snapshot => {
if(snapshot.val()){
return false;
} else {
return true;
}
})
}
const valid = checkCode(element.value);
const message = `${!valid ? 'Code Exists':''}`;
error = !valid ? [valid,message] : error
}
the valid shows = undefined,
my goal is to make the valid shows true/false,
could someone help me, and point out, what did i do wrong?
*I make the first code just to point out that the firebase is actually working
*the second code is the one that I originally used
There are a few issues that are standing out to me.
First, the code that you use originally was using return inside of the function's if / else conditional. I believe this is correct, you'll want to go back to doing that.
Second, the firebase.orderByChild() function that you are calling is a Promise as it has a .then() statement appended to it. What this means is that the function does not synchronously finish executing and return a value. The code below that promise is being run while the firebase function is still processing.
Give this a shot and see if it works, and if you have any further errors beyond the promise.
if(element.validation.codeunique) {
function checkCode(inputcode) {
firebaseUsers.orderByChild('code')
.equalTo(inputcode).once('value')
.then( snapshot => {
if(snapshot.val()){
return false;
} else {
return true;
}
console.log(thecode)
})
}
let message = checkCode(element.value) ? 'Code Exists':'Code Does not Exist';
}
I've done it outside of the function above and by checking it when the user submit the form, and if the code exists, i direct it to form again :
firebaseUsers.orderByChild('code')
.equalTo(mycode)
.once('value')
.then (snapshot => {
if(snapshot.val()) {
alert("Code Exists, Please Choose another");
this.props.history.push('/myscreen')
} else {
//submit the data
}
hopefully this will help someone