Route params to /postTitle not /postId


#1

Hi, I am new to ember, I manage to get my " single post" model and route working if I send them to myapp/post/postId but I want it to make it work with myapp.com/post/postTitle..I can’t fin anywhere how to do that…I tried to change the model to this: model(params) { this.get(‘store’).query(‘post’, { filter: { title: params.post_title } }) }

and router to : Router.map(function() { this.route(‘post’, {path: ‘post/:post_title’}); });

but won’t work… any help?

I am using firebase as the database.


#2

Hi @hodaraadam,

I think the problem may be in your model hook. Firebase uses a different query syntax than most other backends. I think you’ll also need to ‘return’ from your model hook instead of just calling store.query. I think what you want will look more like:

model(params) {
  return this.store.query('post', {
    orderBy: 'title',
    equalTo: params.post_title
  });
}

For (slightly) more on emberfire query syntax see here or check out the general web firebase docs.


#3

Thanks @dknutsen how can I return the object in the promise function just return post ? or data? thanks


#4

Hey @hodaraadam not 100% sure what you’re asking, could you be more specific? What promise function are you referring to? And where are you trying to return to/from? The code that I posted will return the results of store.query, which is a promise. Then the router waits until that promise has resolved and passes the resolved ‘post’ object to your controller/template.


#5

I am trying to get routes to work to /post_title instead of /post_id , but can’t get it to work, I tried the code you suggested before but it won’t work…can’t find anywhere online how to do it…here is an example of an ember app that does it https://www.indiehackers.com/businesses/recurpost you see they use a nice url to a single post instead of ugly /busiensses/id1zczasdr?,thnx


#6

What isn’t working? Are there console errors? Is the model hook returning anything? Can you post a sample of your firebase db? It’s difficult to try and debug anything without more information.


#7

Here is the complete code I have, it doesn’t return the data in the route and I don’t get any console errors either:

Router.js

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

const Router = Ember.Router.extend({
  location: config.locationType,
  rootURL: config.rootURL
});

Router.map(function() {
  this.route('post', {path: 'posts/:post_title'});
});

export default Router;

routes/post.js

export default Ember.Route.extend(ModalRouteMixin, {
        model(params) {
  return this.store.query('post', {
    orderBy: 'title',
    equalTo: params.post_title
  });
}

});

template:

<h2>{{model.title}}</h2>

my model is:

title string and text string and it works find to add a new post to firebase and to return it with the Id like I was doing before which was:

router/post.js

 model(params) {
    	return this.store.findRecord('post', params.post_id)
    }

but can’t figure out how to return the single post with the title in the route instead of id.

thanks


#8

I think maybe one issue you might be running into, or might run into in the future, is that the post title “as is” isn’t URL safe. So let’s say you have a record in your firebase db that looks like this:

{
  title: "This is a post",
  text: "Here is some text"
}

If you tried navigating to <server>/posts/This is a post the browser would change the url to <server>/posts/This%20is%20a%20post because whitespace isn’t allowed. This obviously wouldn’t match the actual post title, which is “This is a post”. If your titles are lowercase strings with no whitespace or special characters the code that you have should work, but if not, you’ll want to make a function that takes a string like “This is a post” and converts it to something like “this_is_a_post”. Then save that to the model too (so it would have title, text, and title_id or somethign like that).

Another option is you could keep your old code where it uses :id as the url parameter and then when creating the post record you actually set the id to “this_is_a_post” instead of letting Ember Data/firebase make the random string id automatically. So it would look like:

this.server.createRecord('post', {
  id: 'this_is_a_post',
  title: 'This is a post',
  text: 'This is some text'
});

#9

Hi @dknutsen , Does the last method actually work? Because I had to use slug titles in my post (which is converting title to dasherized string with a serializer)

@hodaraadam Hi, you might want to check this step by step guide - https://embermap.com/video/friendly-urls-with-slugs

PS: I implemented the the same in my blog - https://ember-blog-ae319.firebaseapp.com and I’m having certain trouble making it a shareable URL (and hence the query parameter workaround) Please let me know if there is any other better way to achieve it. Thanks!

Cheers! :v:


#10

@indieNik yes it should work. I use firebase in our main app at my job and one of the things we store is user preferences and we actually override the id with the name of the view that the preferences are for and then do things like store.findRecord('preferences', 'account-view') and it works great.

The only thing you’d have to be careful about is making sure that the ids are unique, and obviously if you were using the id in the URL like described above you’d want to use a slug for the id, so you’d definitely want to convert the name to a slug either way. So the choice basically becomes: do you set the slug as the ‘id’ or as some other arbitrary attribute? If you set it as ‘id’ you can fetch the post with findRecord, if not you’d need to use query.