How to debug emberjs computed property - ember.js

Let's say I have a computed property that depends on other properties. How can I find out which change on dependency property triggers re-compute on my property. Other than that, is there any way to debug computed chaining?

If your computed properties are in a component, you can try hooking into the didUpdateAttrs hook. didUpdateAttrs fire when values which were passed into the component update. Within the didUpdateAttrs you can check to see what attrs were changed by comparing the old/new values.
didUpdateAttrs: function(attrs) {
// attrs should have access to the old/new values
}
https://guides.emberjs.com/v2.6.0/components/the-component-lifecycle/
didUpdateAttrs runs when the attributes of a component have changed,
but not when the component is re-rendered, via component.rerender,
component.set, or changes in models or services used by the template.
A didUpdateAttrs is called prior to rerender, you can use this hook to
execute code when specific attributes are changed. This hook can be an
effective alternative to an observer, as it will run prior to a
re-render, but after an attribute has changed.
An example of this scenario in action is a profile editor component.
As you are editing one user, and the user attribute is changed, you
can use didUpdateAttrs to clear any error state that was built up from
editing the previous user.

Check that property is trigger by notifyPropertyChange() method. You can use notifyPropertyChange() method to trigger the computed property.

Maybe LOG_BINDINGS can show you what you need.
https://guides.emberjs.com/v2.14.0/configuring-ember/debugging/#toc_log-object-bindings
What I would do is set breakpoints in the computeds that are being depended on.

Related

Ember select element - unable to capture on change event

Ember question - still getting used to Ember, but making progress. Here's my issue: I have a template which references a component; the component contains a select element. The select element displays properly, and I want to update the contents of another select element based on the selection in the first element. However, I have not been able to capture the on change event of the first select element. Here is the component code containing the select:
{{view
"select"
content=types
value=selectedtType
selection=selectedtType
prompt="Select Type..."
}}
So I'm not sure how to reference the on change event in the component template, or where the function itself should go - the component's component.js file, or in the route.js file of the parent template. I've done much research on this, but haven't been able to make it work yet. Any help would be appreciated. Thanks.
Check this JSBin. In this example, I had my dependent select use a computed property as its content. This computed property's single dependent key is the value of the first select. If you are doing this with components, your component needs to take the computed property as the attribute that is the select views' content. Any time the first select changes, it will cause the computed property to recompute and thus update the content of the second select. Even in an example using components, this code would probably sit on the controller to keep your component generic enough that it simply takes a content for its select and displays it rather than controlling the display logic itself.
Other options, have a function that observes the first select value and updates a controller variable that is the second select's content. Now if you're example is more complicated in that the changing select's have different option.valuePath and option.labelPath, you can pass pass those values into your component as well.

How can you observe changes on every item in a model in Ember-cli

I have a model called 'matter_has_user', on a particular page, i will have some number of items of this type. Each of these will be store objects and will have a value called bill_alert which will be connected to a checkbox. So i need to watch all of these checkboxes and when a change occurs, i need to issue a save to the api.
So how can you go about this? Can you set up observers on a certain property for each item of a particular type? How can I set up listeners on each of these checkboxes to fire a specific action?
Assuming your model is a collection of these objects, you can set up an observer on each of them like this:
myObserver: function(){
//do something
}).observes('model.#each.bill_alert')
docs

How should I observe a dynamic set of attributes so that observers get fired any time an attribute is set or changed?

I'm relatively new to the Ember world and have run into a snag.
I've got a search grid with a variable number of filters (set dynamically) that can trigger a change of the search results. Because the filters are set dynamically, I won't know their names (and can't set properties on my controller which I would then observe).
I've set up a JSBin here that shows what I'm attempting: http://emberjs.jsbin.com/walipuceta/1/
I'm wanting to have the filterValuesWatcher observer log to the console when any value is set on the filterValues object / property. In essence I'd like to have an observes('filterValues.*') in effect.
Any suggestions on what I'm missing?

Is it possible to observe a model property after it was loaded?

In my use case I want to invalidate a model when some of its properties change so that the user needs to revalidate before publishing his changes
invalidate: function () {
this.set('model.valid', false);
}.observes('model.solution', 'model.setup', 'model.tests')
the problem (I think) is the observer fires whenever the model changes, including when it is loaded, which may be a time where the model is valid and all attributes didn't change, but since it fires valid is set to false.
using isDirty was not helpful as the model is then always dirty
Incase my intent isn't obvious, what I have is a model that I want to be invalidated whenever some properties change, saving changes while invalid causes to model to be unpublished, it also required that the model be valid in order to publish it (however not to save it).
currently my workaround is to just validate when publishing but I would prefer if I can do the former.
I'm having the same issue, but I've found some workaround that works in my case.
Please see the link below. There is an example of using "observesBefore" function instead of "observes"
How can an observer find out the before and after values of the observed property in Ember.js?
I use observesBefore with arguments to check previous state of the model and the new attribute value being set to find out whether this is the first time the model loaded or changes made by the user.
Yes, tricky situation. Any time a model switches all of those properties have changed. In that case, I'd define invalidate on the model itself, that way the only time they change is when that particular model changes.
App.Foo = DS.Model.extend({
...
valid: true,
invalidate: function () {
this.set('valid', false);
}.observes('solution', 'setup', 'tests')
});

Ember classNameBindings not being called for the sample program

I am facing issue with class name bindings. Here is the jsfiddle code for the same. Logging the number of times binding is called. It is never called when the property is changed.
You appear to have a couple of issues here. Primarily, if you want properties to be recalculated when the contents of an array change, you cannot just depend on the array property itself - it will only fire a change when it is set to a different array. If you depend on myArray.#each instead, your property will be recalculated when the contents change as well.
Next, your template containing the span isn't rendering because you're providing an empty view template in your handlebars view declaration. Change your "HTML" to:
{{view App.contact}}
and your span will appear.
Finally, running Ember.run.sync() does not appear to be enough here. I am not as clear on the reason behind this but...computed properties only update when read (versus observers that update immediately). I would hypothesize that since your computed property is only used by the view and the view may only update on a subsequent run through the JS event loop, your computed property is recalculated only once for all your changes to "subordinates". Change your code to use timeouts and it'll work fine.
Here's a jsfiddle with all of my proposed changes.