I'm gonna give poor information about this because I honestly don't have a clue about how to get more information. The thing is: I have a json object in typescript. So:
- When I use console.log(obj), I can see all it's properties, correcly at the console
- When I try to access one of the properties, its value just disapears (becomes an empty string)
- When I try JSON.stringify(obj) the property and it's value is really missing
- After trying JSON.stringify(obj), in the next code line, console.log(obj) shows the property has really gone.
More interesting things happen when I run the folowing code:
console.log(obj); // shows the property value
console.log(JSON.stringify(obj)); // don't show the property value
console.log(obj); // again shows the property value
The object is very simple, and has no functions in it. Just numbers and strings.
The image bellow shows what the chrome console is printing.The property (matricula) is the one with the problem. The obj is the same in all cases. I'm just doing:
console.log(obj);
console.log(JSON.stringify(obj));
console.log(obj['matricula']);
for (const i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(`${i}: ${obj[i]}, comprimento: ` + obj[i].length);
}
}
Apparently it disapears when I try to access it for the first time (obj['property'] or obj.property). So if I try to console.log the object after the for loop above, the property will be missing.
The problem is not probabilistic, I mean it happens every time this snippet runs.
[EDIT]:
Well, the thing goes like this:
private obj: MyClass1 = new MyClass1();
private newObj: MyClass2 = new MyClass2();
foo() {
this.newObj.matricula = this.obj.matricula;
}
bar() {
setTimeout(() => {
// some code here to do other things
goesToTheDataBaseToGrabData().subscribe((res: MyClass1) => {
this.obj = res;
});
}, 300);
}
Basically, I can't get rid of the setTimeout because of Angular event propagation times related to the Material 2 Autocomplete.
I'm sure that bar() is being called before foo(). In fact bar() is called by a blur event of an input. I garantee that much longer than the 300ms of the timeout, foo() is called by a button click. At this point, the property value is already gone (or, in this case, is not yet set).
The way I solved it is bringing the goesToTheDataBaseToGrabData() observable to the button click handler and take all the button handler logic to the subscriber function:
private obj: MyClass1 = new MyClass1();
private newObj: MyClass2 = new MyClass2();
foo() {
goesToTheDataBaseToGrabData().subscribe((res: MyClass1) => {
this.newObj.matricula = res.matricula;
this.obj = res;
});
}
bar() {
setTimeout(() => {
// some code here to do other things
}, 300);
}
So it left me with two options:
- Something is wrong with Angular model change detection (don't think so)
- Something is wrong with my understanding of how the setTimout works (maybe it's not the 300ms, but something deeper, in the way it works)
[EDIT 2]: Now that I fixed the app, something has come to me a few moments ago. During the tests, while I was making sure that bar(), started by a blur event, was really being called before foo() by more than 300ms, there is a great chance that what I was doing was just click in the page background (not really in another control) to force the blur event. What if this isn't enough to rise the blur event? Don't know if the background is able to be focused. It's not realistic, I know, but as I was looking for a problem at the wrong parts, it's possible that I haven't noticed it. The next thing I did after clicking in the background was clicking on the button that executes foo(). What if this click was, in fact, what took the focus out of the control (that fires the blur event which starts the bar() function)? In this case it kind of explains why the delay is messing with everything.