I have an error when I try to get to URL "/posts" in my Ember app. I get a following error:
Uncaught Error: More context objects were passed than there are dynamic segments for the route: posts.index
Which is really puzzling, because there is no dynamic segment for index, my routes look like this:
Router.map(function() {
this.route('posts', function() {
this.route('new');
this.route('show', {
path: ':post_id'
});
});
});
part of the model (models/posts.js):
import DS from 'ember-data';
let Post = DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
content: DS.attr('string')
});
Post.reopenClass({
FIXTURES: [
{
id: 1,
title: "Random text",
author: "Someone new",
content: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium aspernatur quam qui commodi beatae placeat ducimus aliquam veritatis ullam sed! Sit assumenda aspernatur sunt harum accusamus, repellat labore! Repellendus, corporis!"
}
]
});
export default Post;
My link which I use to get to /posts:
{{link-to 'Posts' 'posts'}}
Additional info: I am using ember-cli-cordova, so my environment.js contains "defaultLocationType: 'auto'" and I am also using fixtures, so I have a following adapter:
export default DS.FixtureAdapter.extend({
host: config.apiUrl
});
Does anybody see any problem which would cause the error? Thank you in advance.
EDIT:
My post route (routes/posts/index.js) looks like this:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('post');
}
});
When I comment out the line where I am getting data from the store, everything works fine, so it looks that the problem is somehow connected with the usage of fixtures maybe. I'll try to create the minimum example on ember jsBin, when I get home.
It was a silly typo at the end - from the error message, I was focusing on the model and route of the index and forgot on a template itself. There is an "each" iterator in which I am creating a link to a detail of the post and there was a typo in a link-to, I had "{{#link-to "posts" post}}" instead of "{{#link-to "posts.show" post}}".
You should use {{link-to 'posts'}} instead of {{link-to 'Posts' 'posts'}}, because you don't have dymanic segments in posts route.
Related
I try to build Rails+Ember app using Ember data.
Model:
export default DS.Model.extend({
name: DS.attr('string'),
content: DS.attr('string'),
image_before: DS.attr('string'),
created_at: DS.attr('date'),
updated_at: DS.attr('date'),
status: DS.attr('number'),
comments: DS.hasMany('comment', {async: true}),
user: DS.belongsTo('user'),
});
and get json like this (json is generated with active_model_serializers)
{"work":{
"id":3,
"user_id":1,
"content":"My first photo",
"image_before": "image_before/original/AnViWyuup5I.png",
"created_at":"2015-08-11T16:57:24.153Z",
"updated_at":"2015-11-13T11:39:44.076Z",
"status":1,
"comment_ids":[13]
},
"comments": [{
"id": 13,
"text": "good!",
"created_at": "2015-09-28T10:34:16.461Z",
"user_id": 2
}]
}
Template is:
<div class="work__img-wrapper">
<img class="work__img" src="{{model.image_before}}">
</div>
<div class="work__content">{{model.content}}</div>
<div class="work__comments-list">
<strong>Comments( {{model.comments.length}} ):</strong>
{{#each model.comments as |comment|}}
<div class="work__comment">
<div class="work__comment-text">{{comment.text}}</div>
</div>
{{/each}}
</div>
At page, I get all information about work and Comments( 0 ), but Ember Inspector at Chrome shows comment.
How i can print comments too?
Your model definition should read:
comments: DS.hasMany('comment', {async: false}),
because the related data is being side-loaded with the response, not being fetched asynchronously.
If this is an Ember 2.0 application, the default async setting is true. From the Ember Blog (http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html, emphasis mine):
In Ember Data 2.0 relationships will be asynchronous by default. Sync
relationships will still be supported but you will need to manually
opt into them by setting { async: false } on your relationships. Ember
Data 1.13 will log a deprecation warning you if you have any
relationships where the async property is not explicitly set.
Additionally you can use ember-watson to help identify cases in your
codebase where you have relationships without an explicit async
property.
Problem solved. By default, DS.hasMany associated IDs are not added to the objects that are serialized (http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html).
Should add
export default DS.ActiveModelSerializer
.extend(DS.EmbeddedRecordsMixin)
.extend({
attrs: {
comments: {serialize: 'ids', deserialize: 'ids'}
}
});
I am in the mids of following: Vic Ramon EmberJS tutorial. I reached the point where I am trying to list the leads and have the following setup:
Adapter
App.Store = DS.Store.extend()
App.ApplicationAdapter = DS.ActiveModelAdapter.extend()
DS.RESTAdapter.reopen
namespace: 'api/v1'
Controller
App.LeadsController = Ember.ArrayController.extend
sortProperties: ['firstName', 'lastName']
Model
App.Lead = DS.Model.extend
firstName: DS.attr('string')
lastName: DS.attr('string')
email: DS.attr('string')
phone: DS.attr('string')
status: DS.attr('string', defaultValue: 'new')
notes: DS.attr('string')
fullName: (->
#get('firstName') + ' ' + #get('lastName')
).property('firstName', 'lastName')
Routes
App.LeadsRoute = Ember.Route.extend
model: ->
#store.findAll 'lead'
Router
App.Router.reopen
location: 'auto'
rootURL: '/'
App.Router.map ()->
#resource 'leads', path: '/'
#resource 'lead', path: 'leads/:id'
Template
<article>
<h1>Leads</h1>
<ul>
{{#each lead in controller}}
<li>{{#link-to 'lead' lead}}{{/link-to}}</li>
{{lead.fullName}}
{{/each}}
</ul>
</article>
The issue simply is when I redirect my browser to http://localhost:3000 it shows me the list of fullNames but doesn't show me the anchor links. Also another thing I seem to get in my chrome browser console is:
Error message: Assertion Failed: Cannot find model name
Bonus Question
From reading a few books an tutorials I understand that you can include mixins as a way of injecting additional properties into Controllers or Views. So for example you can do:
Ember.View.extend(App.Editable)
But can you include a mixin into a model? As in can you do:
App.Lead = DS.Model.extend(App.SomeMixin)
Here is working jsbin for Ember 1.12 jsbin.com/mezakepemu/1/edit?html,js,console
1) Links. You could try
<li>
{{#link-to 'lead' lead}}
{{lead.fullName}}
{{/link-to}}
</li>
or
<li>{{link-to lead.fullName 'lead' lead}}</li>
And in modern Ember versions it's better to write
{{#each lead in model}} ... {{/each}}
or
{{#each model as |lead|}} ... {{/each}}
2) Error message: Assertion Failed: Cannot find model name - please show the code where this error is thrown. Your leads route, controller and template looks normal.
3) Yes, mixins can be included in models and in every Ember.Object.
I'm using the latest ember-cli and currently testing it, creating very simple app using ember-data and http-mock for RESTAdapter - ember generate http-mock api-server
Single post get from the API:
http://localhost:4200/api/api-server/posts/1
Result
{"post":
{
"id":1,
"title":"How to write a JavaScript Framework",
"author":"Tomhuda Katzdale",
"body":"Lorem ipsum dolor sit amet"
}
}
Here are all the relevant codes:
Adapters
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
namespace: 'api/api-server'
});
Model
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
body: DS.attr('string')
});
router.js
import Ember from 'ember';
var Router = Ember.Router.extend({
location: EmbercliDataENV.locationType
});
Router.map(function() {
this.route('application');
this.resource('posts', function() {
this.resource('post', { path: ':post_id' });
});
});
export default Router;
Routes (posts and post) - view and child view
posts route
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('post');
}
});
post route
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.post_id);
}
});
template
posts.hbs
<h2>Posts List</h2>
<ul>
{{#each}}
<li>
{{#link-to 'post' this}}{{title}}{{/link-to}} | {{author}} | {{body}}
</li>
{{/each}}
</ul>
{{outlet}}
post hbs
<h2>Single Post</h2>
<p>Post title: {{title}}</p>
<p>Post author: {{author}}</p>
<p>Post body: {{body}}</p>
THE PROBLEM: if you look at the screen-cap below, in the chrome ember debugger, the single post model is hooked to the post route but is not printed in the post.hbs
Using just the ember starter kit, I got no problem at all with the exact same app.
Thank you for any help, cheers
UPDATE
The following is the exact same Ember app coded using the starter kit, host in xampp and using PHP Slim framework for REST Api. Working FINE!
try to fix your data, because post is nested in posts, try this:
{"post":[
{
"id":1,
"title":"How to write a JavaScript Framework",
"author":"Tomhuda Katzdale",
"body":"Lorem ipsum dolor sit amet"
}]
}
check within your posts hbs if the data is visible, then post should work fine
After browsing the Ember.js forum I got the answer there - http://discuss.emberjs.com/t/strange-behavior-w-retrieving-model-from-controller/6155
It seems when using the Ember generate controller command, you end up with Ember.Controller, not Ember.ObjectController or Ember.ArrayController lol.
I edit my post controller from: (generate by the Ember generate controller command)
export default Ember.Controller.extend({
});
to
export default Ember.ObjectController.extend({
});
and now the model is binding :D
<h2>Posts List</h2>
<ul>
{{#each}}
<li>
{{#link-to 'post' post}}{{title}}{{/link-to}} | {{author}} | {{body}}
</li>
{{/each}}
</ul>
{{outlet}}
1.instead of 'this' use post, hope this will fix the issue
http://emberjs.com/guides/templates/links/#toc_adding-additional-attributes-on-a-link
This app works fine when the store is FixtureAdapter, but will not load has_many relationships when the store is ActiveModelAdapter.
The Route is like this:
App.IndexRoute = Ember.Route.extend({
model: function(){
return this.store.find('post', 1 )
}
});
The models are like this:
App.Post = DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
comments: DS.hasMany('comments', {embedded: 'always'})
});
App.Comment = DS.Model.extend({
text: DS.attr('string'),
post: DS.belongsTo('post')
});
The handlebars template calls for:
{{name}}
{{#each comments}}
{{text}}
{{/each}}
The name appears, the comments do not.
In the ember developer console, the comments are not getting loaded at all.
The server seems to be serving the serialized content correctly (as far as I can tell). It looks like this:
{"post":{"id":1,"name":"Title","description":"Lorem Ipsum","comments":[{"id":1, "text": "commentary here"}]}}
Does anyone know why this isn't working and how I could fix it? I've been struggling with this for hours now and cannot figure out why it's not working. Thanks very much for any insight you can provide.
I'm using this as part of a Rails project, and these are the relevant gems:
gem 'ember-rails'
gem 'ember-source', '1.3.0'
gem 'ember-data-source', '~> 1.0.0.beta.6'
gem "active_model_serializers"
You need to specify a custom adapter for each over-riden model and mixin the Embedded Records Mixin:
App.PostSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
comments: {embedded: 'always'}
}
});
Please see the comments in the Ember-Data source code for more info.
In the following example, using the new Router v2 API, the ember application behaves as expected with one exception. When hovering over the dynamically created links, using a registered #linkTo Handlebars the url shows undefined.
How do I have a slug field in the URL?
Here is the model
App.Todo = DS.Model.extend({
slug: DS.attr('string'),
date: DS.attr('date'),
updated: DS.attr('date'),
task: DS.attr('string'),
description: DS.attr('string')
});
My Router
App.Router.map(function(match){
this.route('index', {path: '/'});
this.resource('todos', {path: '/todos'}, function(){
this.resource('create', {path: '/create'});
this.resource('todo', {path: '/:slug'}, function(){
this.resource('edit', {path: 'edit'});
});
});
});
I know that this does show 'undefined', but this would be a nice (Handlebars)
{{#each todo in tasks}}
<div class="user">
{{#linkTo todo todo.slug}}<h4><i class="icon-list"></i>{{todo.task}}</h4>{{/linkTo}}
<p>{{todo.description}}</p>
</div>
{{/each}}
Thanks for any pointers! I'm using Ember-data also
Here is a example fiddle
http://jsfiddle.net/R2SPs/6/
This works for ember routing v2.1 (01.16.13)
Thanks to rakl on #emberjs on IRC here is a mixin that solves the problem
App.SlugRouter = Ember.Mixin.create({
serialize: function(model, params) {
var name, object;
object = {};
name = params[0];
object[name] = model.get('slug');
return object;
}
});
Now just place that in your Router and your golden
App.TodoRoute = Ember.Route.extend(App.SlugRouter,{
//insert your code
});
The path of the route is "todo.index" with the resource definition:
this.resource('todo', {path: '/:slug'}, ...
So create Route and Controller for it.