Getting Default Values
Here’s a quick look at a common gotcha that slips into pull requests from time to time.
When working in Ember, you’ll often want a default value for
certain properties. Ember provides a convenient means for getting a
default value with the aptly named, getWithDefault
:
Ember.getWithDefault(person, 'lastName', 'Doe');
The above code would retrieve the lastName
property off of the
person
object, and if the value is undefined
, it will return
Doe
.
An Example
Let’s say we’re working on a campaign application with a Donation
model. This
app will primarily be used by Super PACs to fund campaigns
of legislators who represent the interests of a small group of deep-pocketed
individuals. These well-funded legislators will win their elections
about 90% of the time.
Naturally, if the donor does not disclose her name, the Super PACs would like the default donation to display “Anonymous.”
Our first pass looks something like this:
// app/donation/model.js
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import computed from 'ember-computed';
import get from 'ember-metal/get';
export default Model.extend({
amount: attr('number'),
fullName: attr('string'),
displayName: computed('fullName', {
get() {
return get(this, 'fullName') || 'Anonymous';
}
})
});
We soon realize we can clean up our displayName
computed property with getWithDefault
:
displayName: computed('fullName', {
get() {
return getWithDefault(this, 'fullName', 'Anonymous');
}
})
Using getWithDefault
in that example is a bit cleaner and easier to
read.
Then one day, we wire up with a new, external API. The JSON payload from this backend
sends null
for fullName
if the record does not have a
value. Our displayName
no longer defaults to “Anonymous” and we’re
slightly confused. If our fullName
value is falsy, why does
getWithDefault
not return our default value?
Remember, getWithDefault
is not evaluating
whether or not the return value is truthy or falsy: it only returns the
default value if the get
returns undefined
. The value that was once
undefined
is now null
, so getWithDefault
returns null
.
The solution here is probably to cleanup the JSON payload in the
serializer so that null
values are treated as ''
.
But for this contrived example, and for any instance in
which you would like to set a default value based off a falsy return
value, use a good, old-fashioned or
operator:
displayName: computed('fullName', {
get() {
return get(this, 'fullName') || 'Anonymous';
}
})
I hope this prevents a few people from scratching their heads when
getWithDefault
doesn’t behave as expected.
Thanks for reading, and don’t forget to support campaign finance reform this tax season by opting into the Presidential Election Campaign Fund (it’s free)!