In the controller
this.get('store').createRecord(Emb.Painting, {name: n});
this.get('store').commit();
In the template
<ul>
{{#each controller}}
<li>
{{name}}
</li>
{{/each}}
Although you can place a
didCreate: function() {
}
in your model. I could not find any direct callback. I decided to add validation at my view layer.
Related
I have 1 timeline on route posts with 2 types of post: from facebook and from twitter, both with same controller: post with 2 methods: isFacebook and isTwitter.
There's a component for each type of post and an 'post-index' with use this 2 methods to redener the correct component.
Route post with default ArrayController:
<ul class="timeline">
{{#each post in model itemController="posts.post"}}
<li> {{post-index post=post}} </li>
{{/each}}
</ul>
post-index
{{#if post.isFacebook}}
{{post-facebook post=post}}
{{/if}}
{{#if post.isTwitter}}
{{post-twitter post=post}}
{{/if}}
{{yield}}
The problem is when I try render a single post in route post.post with post-index template
route:
export default Ember.Route.extend({
setupController(controller, model) {
this._super(controller, model);
controller.set('model', model);
}
});
template:
<ul class="timeline">
{{#each post in model}}
<li> {{post-index post=post}} </li>
{{/each}}
</ul>
My route posts only works because it have itemController="posts.post"
but post.post don't. What I supposed to do ?
If I understand your question correctly, you are wondering how to pass the post itself to the post to the post property of post-index.
If so, you can modify your code as follows:
<ul class="timeline">
{{#each post in model}}
<li> {{post-index post=this}} </li>
{{/each}}
</ul>
The only change is to change post to this. Since you are in an each block this will pass the item for the current iteration.
Is there a way to use {{yield}} inside a {{each}} helper in a Ember.Component?
So I can provide a repating structure with a component, and maybe a add/remove line functionality, but I can provive handlebars markup from outside and use the {{yield}} helper to access that.
Thats what I wanna do:
items:
[{
name: 'stack',
value: 5
}, {
name: 'overflow',
value: 8
}]
template:
{{#show-list value=items}}
{{name}} - {{value}}
{{/show-list}}
component:
<ul>
{{#each value}}
<li>{{yield}}</li>
{{/each}}
</ul>
And thats what I expect back:
<ul>
<li>stack - 5</li>
<li>overflow - 8</li>
</ul>
This is now possible in Ember using public APIs.
See this twitter post from Yehuda:
https://twitter.com/wycats/status/536723973745410048
And this demo:
http://jsbin.com/yawasisofu/4/edit?html,js,output
In your case, the component should look like:
<ul>
{{#each value as listItem}}
<li>{{yield listItem}}</li>
{{/each}}
</ul>
I was following the tutorial but the tutorial is for the object controller. In an Array controller how do I properly pass in the object for the text field so it triggers the update for that model object?
Right now I can double click, and then type in some value, and if I hit enter I get the value plus undefined method set.
Uncaught TypeError: Object asdasdasdasdasd has no method 'set'
I guess it's passing the raw value into the controller and then trying to run methods off of that. How do I get it to pass the actual model?
View:
<ul>
{{#each}}
<li {{bind-attr class="isEditing:editing"}} {{action "editWorkout" this on="doubleClick"}}>
{{#if isEditing}}
{{view Ember.TextField class='edit' action="updateWorkout"}}
{{else}}
{{#link-to 'workout' this}} {{title}} {{/link-to}}
{{/if}}
</li>
{{/each}}
<li>
{{newWorkoutName}}
</li>
</ul>
Controller:
EmberWorkouts.WorkoutsController = Ember.ArrayController.extend
actions:
editWorkout: (workout) ->
workout.set('isEditing', true)
createWorkout: ->
title = #get('newWorkoutName')
workout = #store.createRecord('workout', title: title)
#set('newWorkoutName', '')
workout.save()
updateWorkout: (workout) ->
workout.set('isEditing', false)
workout.save()
isEditing: false
Repo here if you want to investigate: https://github.com/ecl1pse/ember-workouts/tree/master/app
You can specify an itemController in your each and then use an ObjectController for each item in your list.
{{#each itemController="workout"}}
<li {{action editWorkout on="doubleClick"}}>
<!-- Other stuff goes here -->
</li>
{{/each}}
EmberWorkouts.WorkoutsController = Ember.ObjectController.extend({
editWorkout : function(){
this.set('isEditing', true);
}
});
Here's a JSBin of the general idea : http://jsbin.com/ucanam/1038/edit
I want to implement item-list/item-detail pattern in Ember, but the nuance is that the detail view must appear next to the selected item. E.g:
<ul>
<li><div>Post 1<div></li>
<li><div>Post 2<div></li>
<li><div>Post 3<div></li>
<li>
<div>Post 4<div>
<div>
<ul>
<li>Comment 1</li>
<li>Comment 2</li>
<li>Comment 3</li>
</ul>
</div>
</li>
<li><div>Post 5<div></li>
</ul>
The Handlebars template I tried is:
<script type='text/x-handlebars' data-template-name='posts'>
<ul>
{{#each model}}
{{#linkTo 'post' this}}
<div>{{title}}</div>
{{/linkTo}}
{{#if isSelected}} <!-- How to implement isSelected ? -->
<div>{{!-- render selected post's comments --}}</div>
{{/if}}
{{/each}}
</ul>
</script>
I tried this in controller:
App.PostController = Em.ObjectController.extend({
isSelected: function() {
return this.get('content.id') === /* what to put here? */;
}
});
What I'm stuck with is how to implement isSelected in 'Ember'-way? Am I going in right direction?
You are on the right track. The trick is to use a different controller to wrap products in the item-list vs. the item-detail. So start by specifying that the handlebars {{each}} helper should wrap each entry in a ListedProductController
{{#each model itemController="listedProduct"}}
Now define ListedProductController, adding the isSelected function you'd been writing. Now it can reference the singleton ProductController via the needs array, comparing the product that was set by the router to the listed product.
App.ProductController = Ember.ObjectController.extend({});
App.ListedProductController = Ember.ObjectController.extend({
needs: ['product'],
isSelected: function() {
return this.get('content.id') === this.get('controllers.product.id');
}.property('content.id', 'controllers.product.id')
});
I've posted a working example here: http://jsbin.com/odobat/2/edit
So my models are set up like this :
App.Post = DS.Model.extend
comments: DS.hasMany 'App.Comment'
App.Comment = DS.Model.extend
post: DS.belongsTo 'App.Post'
I'm trying to create a view that has all posts and all comments display, but I need to decorate the comment objects.
This is what I'd like to do but, to no avail :
<ul>
{{#each post in controller}}
<li>{{post.title}}</li>
<ol>
{{#each comment in post.comments itemController="comment"}}
<li>{{comment.body}}</li>
{{/each}}
</ol>
{{/each}}
</ul>
Properties defined in a App.CommentController are simply not found by the template.
I suspect that Ember.OrderedSet does not implement the itemController param - is there a workaround for this?
You need to use the new expiremental control tag. This will load the view and controller for the specified type:
<ul>
{{#each post in controller}}
<li>{{post.title}}</li>
<ol>
{{#each comment in post.comments}}
{{ control "comment" comment }}
{{/each}}
</ol>
{{/each}}
</ul>
You will need to enable this expiremental feature first. Put this before ember is loaded:
<script type='application/javascript'>
ENV = {
EXPERIMENTAL_CONTROL_HELPER: true
};
</script>
Also, you will need to specify that the controller for comments should not be a singleton, otherwise there will only be one controller instantiated for all comment views:
// this is needed to use control handlebars template properly per
// https://github.com/emberjs/ember.js/issues/1990
App.register('controller:comment', App.CommentController, {singleton: false });