Aurelia prints __observers__ instead of object
Asked Answered
R

2

1

I am trying to bind an object from the view-model to view as follows:

// welcome.js
export class Welcome {

constructor() {
    this.data = {
        a: "",
        b: "",
        c: ""
    }
}

submit() {
       console.log(this.data);
    }
}


// welcome.html
<form role="form" submit.delegate="submit()">
    <div class="form-group">
      <textarea class="form-control" value.bind="data.a" rows="3"></textarea>
    </div>
    <button type="submit" class="btn btn-default">Submit</button>
</form>

Ideally, it should print only data object. However, it prints following output in the console.

enter image description here

I would like to know what is observers object and how can I access only data object. Thank you.

Rouen answered 13/2, 2018 at 23:47 Comment(0)
I
2

Short answer:

The __observers__ object is what makes change detection possible for Aurelia, you cannot get rid of that. If you really need to extract precisely what you want then you need to do that by hand.

A bit more in-depth

Normally, when you define some data on the viewmodel, developers typically don't mind setting up properties explicitly, they use the field notation instead, since this is more concise. However, fields are just fields, what happens on read or assignment cannot be altered1.

Whenever a property that is bound to by any means - such as using it in template interpolation (${ data.a }) or binding (<input value.bind="data.a" />), etc. - changes, then Aurelia needs a way of being notified if and when the value changes so it can update anything that relies on it, such as parts of your view.

Because of 1, if something is defined as a field, it is not possible. So what Aurelia does is that it transforms fields on your classes on the fly into properties since they still allow the x = 1 notation (what you use when dealing with fields) unlike the Java-style get-set methods (setX(1)) letting your code work exactly as intended but they also enable executing arbitrary logic both in the getter as well as the setter. As it transforms the fields into properties, it also injects some logic of its own which notifies Aurelia whenever the value changes.

That's why those things are added to your object and that's why you cannot get rid of them. They are absolutely necessary to enable the framework to do its job.


On a side note, of course, there are other ways to enable change detection, but each of them comes with its own quirks. For example, in Angular, this is not necessary, because what Angular does is it executes change checks whenever some asynchronous event occurs:

Angular executes template expressions after every change detection cycle. Change detection cycles are triggered by many asynchronous activities such as promise resolutions, http results, timer events, keypresses and mouse moves.

Of course, this comes with different complications, such as you need to write code like this every now and then just to set some value:

setTimeout(() => this.someVal = 0, 0);

which is really hacky in my opinion.


So basically there are two ways for a framework to get notified when something changes. One is the Aurelia way and the other is the Angular way.

The Aurelia way comes with the consequences that you are asking about, that is, it adds some other stuff to your objects.

Angular, on the other hand, necessitates such hacky solutions as above and one might also wonder about the performance implications of doing change checks in response of most async events.

Idette answered 14/2, 2018 at 9:2 Comment(2)
Man.. that's a limo of an answerLounge
This answer is long winded and unhelpful.Tatouay
L
1

To get your plain object you can use a cloning technique: console.log(JSON.parse(JSON.stringify(this.data)))

Lounge answered 20/2, 2018 at 20:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.