Emberjs how to create a new belongsTo item - ember.js

I'm working on a simple todo app where each todo item belongs to a user. I'm getting this error:
Uncaught Error: Nothing handled the action 'createTodo'.
I think I'm missing a route and maybe a controller, but I'm not really sure what I need to do.
app/router.js:
import Ember from 'ember';
var Router = Ember.Router.extend({
location: TodoENV.locationType
});
Router.map(function() {
this.route('about');
this.resource('users', function() {
this.route('show', {path: ':user_id'});
});
});
export default Router;
app/routes/users/index.js:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('user');
}
});
app/models/user.js:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
todos: DS.hasMany('todo')
});
app/models/todo.js:
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
user: DS.belongsTo('user')
});
app/controllers/todo.js:
import Ember from 'ember';
export default Ember.ArrayController.extend({
actions: {
createTodo: function() {
var title = this.get('newTitle');
if (!title.trim()) { return; }
var todo = this.store.createRecord('todo', {
title: title // how do I get the user id?
});
this.set('newTitle', '');
todo.save();
}
}
});
app/templates/users/show.hbs:
<h4>{{name}}</h4>
<h5>Todos</h5>
{{input type="text" id="new-todo" placeholder="new todo"
value=newTitle action="createTodo"}}
<ul>
{{#each todos}}
<li>{{title}}</li>
{{/each}}
</ul>

The problem is createTodo is implemented in TodoController whereas you are using createTodo action in users/show template. Action is sent to the UsersShowController where createTodo is not implemented. Move createTodo action into UsersShowController and everything should be OK.

Related

Using and binding JSONAPI attributes data in ember js

I have an ember.js toy application that I want to hook into a JSONAPI REST service for obtaining and displaying data. I can trace in my browser's developer console, that indeed, ember-data initiates the appropriate GET requests and receives proper, valid JSONAPI response bodies.
// ./app/models/person.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
birthdate: DS.attr('string')
});
// ./app/adapters/person.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
pathForType() {
return "persons";
}
});
// ./app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
host: 'http://localhost:5000'
});
// ./app/router.js
import EmberRouter from '#ember/routing/router';
import config from './config/environment';
const Router = EmberRouter.extend({
location: config.locationType,
rootURL: config.rootURL
});
Router.map(function () {
this.route('persons', function() {
this.route('show', { path: '/:person_id' });
});
});
export default Router;
// ./app/routes/persons/show.js
import Route from '#ember/routing/route';
export default Route.extend({
model(params) {
return this.get('store').findRecord('person', params.person_id);
}
});
// ./app/routes/persons/index.js
import Route from '#ember/routing/route';
export default Route.extend({
model() {
return this.get('store').findAll("person");
}
});
// ./app/routes/application.js
import Route from '#ember/routing/route';
export default Route.extend({
});
// ./app/app.js
import Application from '#ember/application';
import Resolver from './resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
const App = Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver
});
loadInitializers(App, config.modulePrefix);
export default App;
// ./app/resolver.js
import Resolver from 'ember-resolver';
export default Resolver;
Unfortunately, when I want to use the model in my template, I can only access the element ids, and not the data attributes like name (Remains empty when rendered).
<!-- ./app/templates/persons/index.hbs -->
{{#each model as |person index|}}
<li>
Person {{person.id}} {{index}}
{{person.name}}
{{#link-to 'persons.show' person }}
Link {{index}}
{{/link-to}}
</li>
{{/each}}
I am a bit at loss for why this happens. Am I doing something wrong?
The posted code is fine, the attributes I was missing in the templates was actually missing from the HTTP responses.

Ember Why can't the model data be rendered into template?

So I've been beating my head against this for a few days now. I can't get my model data to render in the template at all. No errors are being thrown. Looking in the Ember Inspector, the Data tab shows my record loaded in tasks.
Any help much appreciated.
// app/adapters/application.js
import Ember from 'ember';
import FirebaseAdapter from 'emberfire/adapters/firebase';
const { inject } = Ember;
export default FirebaseAdapter.extend({
firebase: inject.service(),
});
// app/routes/tasks.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.store.findAll('task');
},
});
// app/model/task.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
description:DS.attr('string'),
date: DS.attr('date'),
created: DS.attr('string',{
defaultValue:function(){
return new Date();
}
})
});
// app/templates/tasks.hbs
<h2>tasks</h2>
{{#each task in model}}
<h2>{{task.title}}</h2>
{{/each}}
Ember Inspector:
View Tree:
tasks emtasks/templates/tasks <DS.RecordArray..> tasks --
Data:
task(11)
You are using a newer version of ember. Try this:
// app/templates/tasks.hbs
<h2>tasks</h2>
{{#each model as |task|}}
<h2>{{task.title}}</h2>
{{/each}}

How to set the class of an Ember component based data in the model?

I'm trying to setup the class name for the component which based on the data property. I succesfully set data to the template.hbs and I see that component is rendered. But inside the component.js I can't set the classname
export default Ember.Component.extend({
tagName: 'li',
classNameBindings: ['complete:completed'],
complete: Ember.computed('isCompleted', function(){
return this.get('isCompleted');
})
});
This is not working. Class name doesn't calculated. How can I do this?
This is my route:
export default Ember.Route.extend({
model: function(){
return Ember.RSVP.hash({
todoList: this.store.findAll('todo')
});
}
});
and template.hbs
{{#each todoList as |todo|}}
{{todo-item todo=todo}}
{{/each}}
export default Ember.Component.extend({
tagName: 'li',
classNameBindings: ['todo.isCompleted:completed']
});

Sort model by id

I sideload products of a given category. The problem is that they are not sorted. I'd like to sort them by id and render the sorted products in a select.
How can I sort them?
app/category/model.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
products: DS.hasMany('product', { async: true })
});
route.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return {
category: this.store.find('category', 1)
};
}
});
template.hbs
{{view "select" prompt="All products"
content=model.category.products
optionLabelPath="content.name"
optionValuePath="content.name"
value=selectedProduct
class="form-control"}}
You can use a computed property and the Ember.SortableMixin to sort the products in your controller:
sortedProducts: Ember.computed('model.category.products', function() {
return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
sortProperties: ['id'],
sortAscending: true,
content: this.get('model.category.products')
});
})
And then simply use sortedProducts instead of model.category.products.
Source

Ember select not binding to a property in the model

If I understand the ember.js documentation correctly then I should see the models systemStatus value get populated, but I'm not:
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Description</label>
<div class="col-sm-10">
{{view "select" content=statuses value=model.systemStatus }}
</div>
</div>
This is the controller:
import Ember from "ember";
export default Ember.Controller.extend({
statuses: ["Being Built", "Active","Inactive"],
selectedSystemStatus: 'Active',
actions: {
save: function() {
// this.model.set('systemStatus', this.selectedStatus);
var s = this.get('selectedSystemStatus');
this.model.save();
},
cancel: function() {
}
}
});
The model:
import DS from "ember-data";
export default DS.Model.extend({
name: DS.attr('string', {defaultValue: 'Hello'}),
systemStatus: DS.attr('string', {defaultValue: 'Active'}),
description: DS.attr('string', {defaultValue: 'Describe me'})
});
The router:
import Ember from "ember";
export default Ember.Route.extend({
model: function() {
return this.store.createRecord('software-system');
}
});
Everything works up until you try to select an option from the UI. I'm not sure what I'm doing wrong here, and would like some help.
do you have any place where you call this.store.find('my-model')? This is where the model gets populated.
The default way would be to put it into a corresponding route in the model hook:
// routes/my-model.js
export default Ember.Route.extend({
model: function() {
return this.store.find('my-model');
}
});
With this approach, your controller will wait until the model is loaded.