Reputation: 8477
Just getting started with Ember.js and already have a stupid question! I would like to encapsulate some functionality (that will be called by several different routes). I'm not quite sure where to put it.
The "procedure" should do the following:
htmlSafe()
on the HTML-formatted content property of the object. Here's what I've tried so far:
model()
) that does the data retrieval and a helper that does the data formatting. This works, but seems clumsy? This is a greenfield app so I'm using canary for a bit of future-proofing. I don't want to use triple-curlies for that reason. Here's my code for the middle (working) option:
app/routes/tos.js:
import Ember from 'ember';
import wpJson from '../utils/wp-json';
export default Ember.Route.extend({
model() {
return wpJson('terms-of-use');
}
});
app/utils/wp-json.js:
/* global Ember */
export default function wpJson(slug) {
var url = `/wp-json/posts?type[]=page&filter[name]=${slug}`;
return Ember.$.getJSON(url).then(data => {
return data.shift();
});
}
app/templates/tos.hbs:
{{html-safe model.content}}
app/helpers/html-safe.js:
import Ember from 'ember';
export function htmlSafe([html]) {
return html.htmlSafe();
}
export default Ember.Helper.helper(htmlSafe);
In some kind of a perfect world, app/routes/tos.js
would be empty and app/templates/tos.hbs
would look more like this:
{{wp-foo-bar slug='terms-of-use'}}
Thanks in advance for any suggestions or feedback.
Upvotes: 0
Views: 82
Reputation: 8477
Here's my final solution, based off of Deewandra's solution (which I've marked "correct"). The main difference is the use of ic-ajax, which the folks in #emberjs on Freenode strongly recommended for various reasons. I also deleted the html-safe
helper and moved the htmlSafe()
function call inside the component.
The only thing I'm still confused about is some intermittent warnings I've been seeing about not setting properties from within the didInsertElement()
hook. I guess I'll keep an eye on it as Ember.js 2.0 matures and my understanding of the framework continues to improve.
app/components/wp-get-page.js:
import Ember from 'ember';
import ENV from '../config/environment';
import ajax from 'ic-ajax';
export default Ember.Component.extend({
slug: null,
isLoadingData: false,
remoteData: null,
didInsertElement() {
const slug = this.get('slug');
if (Ember.isEmpty(slug))
throw new Error('slug not specified in wp-get-page call');
this.set('isLoadingData', true);
ajax(`${ENV.APP.WP_API_URL}/posts?type[]=page&filter[name]=${slug}`)
.then(data => {
if (Ember.isEmpty(data))
throw new Error('no data from wp-json');
if (Ember.isArray(data) && data.length === 1)
data = data.shift();
this.set('remoteData', {
title: data.title,
content: data.content.htmlSafe()
});
})
.catch(() => {
this.set('remoteData', {
title: 'Sorry',
content: 'Unable to retrieve page contents! Please try again later.'
});
})
.finally(() => {
this.set('isLoadingData', false);
});
}
});
Upvotes: 0
Reputation: 2465
How about putting all the logic in a component itself, like this:
//app/components/wp-foo-bar/component.js
import Ember from 'ember';
export default Ember.Component.extend({
remoteData: null,
loadingData: false,//maybe show spinner depending on this
fetchRemoteData: function(slug){
var url = '/wp-json/posts?type[]=page&filter[name]='+slug;
return new Ember.RSVP.Promise(function(resolve, reject){
Ember.$.getJSON(url, function(data){
resolve(data.shift());
});
});
},
didInsertElement: function(){
var slug = this.get('slug');
this.set('loadingData', true);
this.fetchRemoteData(slug).then(function(data){
this.set('remoteData', data);
this.set('loadingData', false);
}.bind(this));
}
});
And the template for the component would look like:
{{html-safe remoteData}}
Upvotes: 1