0
votes

I'm attempting to create a simple application with several dynamic pages: index, about, and contact. I don't want to hardcode the routes in the router; the user could potentially add pages without having to edit the router. I begin with Ember-cli.

I found a tutorial online that briefly covers this task: http://mavilein.github.io/javascript/2013/09/28/three-steps-to-ember-js-seo-friendly-urls/. Unfortunately, I can across two major problems when using it with Ember Data:

  1. this.store.find("page", params["page_id"]); return san array, not a object. It really isn't designed for retrieving a single object.

  2. The serialize function on the Route never gets called.

Adapter

import DS from 'ember-data';

export default DS.FixtureAdapter.extend({
    queryFixtures: function(fixtures, query, type) {
        var key = Ember.keys(query)[0];
        return fixtures.filterBy(key, query[key]); //This must be an array, not an object.
    }
});

Model

import DS from "ember-data";

var Page = DS.Model.extend({
    title: DS.attr(),
    body: DS.attr()
});

Page.reopenClass({
    FIXTURES: [
        {
            id: 1,
            title: "Contact",
            body: "Aenean lacinia bibendum nulla sed consectetur. Curabitur blandit tempus porttitor. Maecenas faucibus mollis interdum. Maecenas sed diam eget risus varius blandit sit amet non magna.",
            path: "contact"
        },{
            id: 2,
            title: "About",
            body: "Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Curabitur blandit tempus porttitor. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.",
            path: "about"
        }
    ]
});

export default Page;

Router

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
    this.resource("page", {"path": "/:page_id"});
});

export default Router;

Route (Page)

import Ember from "ember";

export default Ember.Route.extend({
    model: function(params) {
        return this.store.find("page", {"path": params["page_id"]});
    },
    serialize: function() {
        alert("serialize"); //is never called
    }
});

Template

{{title}} //Must be wrapped in {{#each}} in order to loop through the array of a single object

The only way I have actually made this work, is to change the integer id to a string that matches the URL. This approach feels like it is destroying the model; I assume this is not the correct approach.

1
this.store.find("page", params["page_id"]); should never return an array.Peter Brown

1 Answers

1
votes

find() should always returns an array if the second arg is an object, as it then calls findQuery(). That doesn't matter though you can just get the first one and return it in a new promise:

export default Ember.Route.extend({
    model: function(params) {
        var query = this.store.find("page", { path: params.page_id });

        var promise = new Ember.RSVP.Promise(function(resolve, reject) {
           query.then(function(result) {
               resolve(result.get('firstObject'));
           },
           function(err) {
               reject(err);
           });
        });
        return promise;
    },
});

serialize is only called to get the param from the model, so only on thing like {{link-to 'page'}}