Reputation: 187
I've build a computed property inside my model to run a calculation on distance to a location using user location and point of interest location (in this case vineyards). The calculation seems to take a second and the template renders even when the milesAway attribute has not been set. Thus not rendering the pertinent information. Any ideas? Model code below...
import DS from 'ember-data';
import attr from 'ember-data/attr';
import { belongsTo, hasMany } from 'ember-data/relationships';
import EmberObject, { computed, observer } from '@ember/object';
import { inject as service } from '@ember/service';
export default DS.Model.extend({
featuredImages: hasMany('contentful-asset'),
featured: attr('boolean'),
name: attr('string'),
slug: attr('string'),
rating: attr('number'),
location: attr('string'),
latitude: attr('string'),
longitude: attr('string'),
bodyOne: attr('string'),
milesAway: attr('string', {async: false}),
googleMapsApi: Ember.inject.service(),
googleLocation: computed(function() {
let userLocation = 'Hard Coded Test Address';
let endLocation = this.get('location');
let milesAway = '';
let googleMapsApi = this.get('googleMapsApi');
this.get('googleMapsApi.google').then((google) => {
var self = this;
let distanceMatrixService = new google.maps.DistanceMatrixService();
function calculateDistance() {
distanceMatrixService.getDistanceMatrix({
origins: [userLocation],
destinations: [endLocation],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.IMPERIAL,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
self.toggleProperty('errorState');
} else {
if (response.rows[0].elements[0].status === "ZERO_RESULTS") {
self.toggleProperty('errorState');
} else {
var distance = response.rows[0].elements[0].distance;
var distance_text = distance.text;
self.set('milesAway', distance_text);
}
}
}
calculateDistance();
});
})
});
Upvotes: 0
Views: 198
Reputation: 666
A few things stand out...
Your computed property googleLocation
is missing it's dependencies, which will prevent it being updated. At the very least, location
should be listed.
Also, computed properties are meant to be 'pure functions', so that they have no side-effects whenever they are executed. So, instead of setting milesAway
within the computed function, you should return a value from your computed function, which may as well be named milesAway
. I can't comment too much on the distance calculation part as I've not done that yet myself.
You should remove this line from your code:
milesAway: attr('string', {async: false}),
and do something like the following structure:
milesAway: computed('location', function() {
let location = this.get('location');
// Your code to calculate the distance
return distance;
})
However, models are essentially intended for persistent data rather than transient application data. milesAway will vary per user (I see you have a hardcoded userLocation while you're working on this) for each vineyard that uses this model. So, you probably want to move this computed property out of your model and into your component or controller. So, in your component or controller, you'd have:
milesAway: computed('model.location', function() {
let location = this.get('model.location');
// Your code to calculate the distance
return distance;
})
Upvotes: 2