jeudi 30 juin 2016

Dynamic segments other than id in Ember.js

I'm trying to wrap my head around dynamic segments and I want to be able to use a slug or other property instead of the id. When I can get things working it feels like a fluke. (I'm using ember 2.7+)

I plan on using ember-data, but I want to ensure I'm in control - and so I don't want to use the :post_slug / underscore style that has some built in magic that I want to avoid.

Here is an ember-twiddle Here are step-by-step commits in a github repo



My thought process


1. Conceptually, lets say I need a list of cats - so I need to describe the model for what a 'cat' is.

models/cat.js

import Model from "ember-data/model";
import attr from "ember-data/attr";

export default Model.extend({
  name: attr('string'),
  slug: attr('string')
});


2. define where the dynamic segment will be in the url. I'm going to use catId to prove a point instead of cat_id or :id like most of the tutorials I've seen. For this example, I'm also writing an actual app structure instead of the smallest router possible - to test the edges of this.

router.js

Router.map(function() {
  this.route('index', { path: '/' });
  this.route('cats', { path: '/cats' }, function() {
    this.route('index', { path: '/' }); // list of cats
    this.route('cat', { path: '/:catId' }); // cat spotlight
  });
});


3. pull in the catData into the store ~ in the /cats route

routes/cats.js

import Ember from 'ember';

const catData = [
  {
    id: 1,
    name: 'Dolly',
    slug: 'dolly'
  },
  {
    id: 2,
    name: 'kitty cat',
    slug: 'kitty-cat'
  },
  {
    id: 3,
    name: 'Cleopatra',
    slug: 'cleo'
  }
];

export default Ember.Route.extend({
  model() {
    return catData;
    // return this.get('store').findAll('cat'); // with mirage or live api
  }
});


4. create the templates... + set up the 'cat' route. The records are in the store... right? so I should be able to 'peek' at them based on id. The docs use params - but - "Ember will extract the value of the dynamic segment from the URL for you and pass them as a hash to the model hook as the first argument:" ~ and so the params can really be anything you want... and is just replaced with the dynamic segment - so to that point / I'm using 'passedInThing' just to assert control over the confusing conventions (many tutorials use param instead of params)

routes/cats/cat.js

model( passedInThing ) {
  return this.store.peekRecord('cat', passedInThing.catId );
}


5. At this point, I should be able to navigate to the url /cats/2 - and the 2 should get passed through the model hook - to the query. "Go get a 'cat' with an id of 2" --- right??? ((the twiddle example uses a hard-coded set of catData - but in my other attempts I'm using mirage: http://ift.tt/29eTvpR


6. Typing in the segment works - but for link-to helpers I need to pass in the explicit cat.id


  <span></span>



7. I can get all that working - but I don't want an ID in the URL. I want cats/cleo with the 'slug' ~ in theory I can just switch catId for catSlug and cat.id to cat.slug etc - but that is not the case. I've seen many tutorials outlining this but they are outdated. I've tried passing in { slug: params.slug } and every combo of find query and peek etc. Sometimes the url will work but the model wont render - or the opposite.


8. This seems like 101 stuff. Can anyone explain this to me? Oh wise emberinos - come to my aid!




Aucun commentaire:

Enregistrer un commentaire