How can I change a data parameter in Angular 2? - arrays

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.

Related

Arraylist doesn't get refilled and/or filtered

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));
},
});
}

handleChange event Typescript

I am trying to implement search bar but it seems it doesn't work.
const [dataCoupons, setDataCoupons] = useState<Coupon[] | undefined>(coupons);
const handleChange = (e: ChangeEvent<HTMLInputElement> & { length: number }) => {
let couponsFilter = dataCoupons;
if (e.length > 0) {
Object.keys(e).forEach((k) => {
if (e[k].value === 0) {
couponsFilter = couponsFilter
?.slice()
.filter((x) => x.durationType.localeCompare('ONCE') === 0);
}
if (e[k].value === 3) {
couponsFilter = couponsFilter?.slice().filter((x) => x.valid === true);
}
if (e[k].value === 4) {
couponsFilter = couponsFilter?.slice().filter((x) => x.valid === false);
}
});
} else {
couponsFilter = coupons;
}
setDataCoupons(couponsFilter);
};
<Select
onChange={handleChange}
isMulti
options={options}
isClearable={isClearable}
classNamePrefix='select'
/>
I have an error message for each e[k]
What am i missing ?
There are two main things stopping you from getting value.
You're protecting with if (e.length > 0) {}
e does not normally have length property because it is an object. If you watched closely, TypeScript does tell you that. It is why you had to add & { length: number } to stop TypeScript from complaining.
If you were to do something like below (without the above mentioned protection)
Object.keys(e).forEach((k) => { console.log(k) })
And then went and triggered change event, you would be able to observe that the console is printing out string keys of all the properties that are attached to e object directly.
One of those properties is target property. You are most likely after that property. Going along the lines of your thinking (how you wrote your code), you would most likely need something like below:
Object.keys(e).forEach((k) => {
if (k === "target") {
console.log(e[k].value);
}
});
The above will capture value from the input field.
I have to warn you though that it seems like a very unsustainable way of creating forms and getting their values. It would be probably best to read this before you proceed.
Also, here's Sandbox to see it in action in most simple implementation.

How to handle null values on first render?

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 )
}
}

AngularJS filter where checking if array parameter contains value

I have simple function to set active state for nav based on url:
angular.forEach(this.$filter('filter')(this.fullNav, {
'link': this.$location.$$path
}, true), (item) => {
item.active = true;
});
Now I want to add legacy URLs to be also highlighted. Instead of link I have links (if there are more then one, but I can make all links parameters to be arrays.
To have it work with links and link paramaters I made change to this:
angular.forEach(this.fullNav, (item) => {
if(item.links) {
if(item.links.includes(this.$location.$$path)) {
item.active = true;
}
} else {
if(item.link === this.$location.$$path) {
item.active = true;
}
}
});
How can I write the second function in $filter form? Or at least without if else statement (by removing link property and having only links property).
you can try following code which is similar to the code you have added.
angular.forEach(this.$filter('filter')(this.fullNav, (item) => {
return Array.isArray(item.links) && item.links.includes(this.$location.$$path);
}, true), (item) => {
item.active = true;
});

firebase function state pending and return undefined

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

Resources