How to find and delete a specific record in Ember - ember.js

I am totally newbie in Ember. I would like to find a record in todos array then delete it. I know I have to pass a parameter to function to find it first then delete it, but I had no luck. Here are related files:
todos.hbs:
{{#each todo in model}}
<li>
<label>{{#link-to "todos.show" list}}{{todo.title}}{{/link-to}}</label>
<button type="button" class="destroy" {{action "deleteTodo"}}></button>
</li>
{{/each}}
I put deleteTodo action in toods routes.
todos routes :
export default Ember.Route.extend({
model: function() {
return this.store.find('todo');
},
deleteTodo: function() {
// Function itself
});
Thanks

Move the deleteTodo method into an action on your routes controller instead of on the Route. Then pass your current todo into your controllers deleteTodo method:
<button type="button" class="destroy" {{action "deleteTodo" todo}}></button>
Looks like your are using ember-cli so the controller would look something like
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
deleteTodo: function(todo){
todo.destroyRecord();
}
}
});

Related

How can we get the original event in ember controller action

How can we get the original event in ember action while handling action inside controller?
Controller
import Ember from 'ember';
export default Controller.extend({
showDetails:function(id)
{
// I want like $(this).position().top
}
});
Template
{{#each item in list}}
<em {{action "showDetails" item.id bubbles=false}}></em>
{{/each}}
{{#each item in list}}
<em onclick={{action "showDetails" item.id}}></em>
{{/each}}
In controller,
import Ember from 'ember';
export default Controller.extend({
actions: {
showDetails(id, event) {
//i want like $(this).position().top
}
}
});

Ember 2 action sent to route instead of component

In my app I've defined this component:
// components/buy-functions.js
export default Ember.Mixin.create({
actions: {
openModal: function() {
$('#buyModal').openModal();
}
}
});
then in the route's template:
<h5>Buy form</h5>
{{#buy-functions}}
<div class="btn" {{action "openModal"}}>Buy</div>
{{/buy-functions}}
(the component does not have a template)
But when i click the button I get the error "nothing handled the "openModal" action...
Can someone explain what I'm doing wrong here?
You need to send your action to route
openModal: function(modalName) {
this.sendAction('openModal',modalName);
}
}
change your button to
<div class="btn" {{action "openModal" 'myModal'}}>Buy</div>
and then in your route
openModal: function(modalName) {
//do whatever you want
}
But another way would be:
let's change your component to
// components/buy-functions.js
export default Ember.Component.extend({
actions: {
openModal: function() {
$('#buyModal').openModal();
}
}
});
then create your component template
// tempaltes/components/buy-functions.hbs
<div class="btn" {{action "openModal"}}>Buy</div>
and then in your route template only use your component name
{{buy-functions}}
I wrote these codes on the fly. hope it works for you.
There is an add-on (ember-route-action-helper) that provides a helper (route-action) for just this very use case.
There's a blog about it.

ember - combining data for two models into single result for power sort

I'm getting data from two models in one of my routes using RSVP hash, and then trying to combine those results in my controller so that they can be used in a select for power sort. However something doesn't seem to be working.
My route looks like this:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
newBook : this.store.createRecord('book'),
authors : this.store.findAll('author'),
publishing_houses : this.store.findAll('publishing-house')
});
},
setupController(controller, model) {
this._super(...arguments);
Ember.set(controller, 'authors', model.authors);
Ember.set(controller, 'publishing_houses', model.publishing_houses);
},
actions: {
save() {
this.modelFor(this.routeName).get('newBook').save();
}
}
});
My template looks like this:
<form {{action "save" on="submit"}}>
{{input value=model.newBook.title placeholder="Title"}}<br>
{{input value=model.newBook.price placeholder="Price"}}<br>
{{#power-select class="select"
selected=model.newBook.author
options=model.authors
onchange=(action (mut model.newBook.author)) as |author|}}
{{author.name}}
{{/power-select}}
{{#power-select class="select"
selected=model.newBook.publisher
options=model.publishers
onchange=(action (mut model.newBook.publisher)) as |publisher|}}
{{publisher.name}}
{{/power-select}}
<input type="submit" value="Save">
</form>
and my controller, which I think is the problem looks like this:
import Ember from 'ember';
export default Ember.Controller.extend({
publishers: function() {
var authors = this.get("authors");
var publishingHouses = this.get("publishing_houses");
return authors.concat(publishingHouses);
}
});
I'm still figuring out how to use controllers. Am I accessing the model data correctly in the controller? Also is this the proper way to create a property to be used in a template?
In setupController hook, you don't need to explicitly set authors and publishing_houses since it will be set by default through super function call.
In your controller, you can try accessing it like this.get("model.authors") and in the same way for other properties publishing_houses, newBook
To access RSVP return model from route, you should access it directly without get function.
`this.modelFor(this.routeName).newBook.save()
For concatenation and other stuff you refer http://emberjs.com/api/classes/Ember.Enumerable.html
reduce might suite your needs.

Call action from parent component in Ember 2.x

I am trying to call an action from a parent component in my route view.
mychild.hbs
{{#parent as |wrapper|}}
<button {{action "animate"}}>Login</button>
{{/parent}}
parent.hbs
<div>{{yield}}</div>
mychild route (no actions)
export default Ember.Route.extend(
});
mychild controller
export default Ember.Controller.extend({
});
parent component
export default Ember.Component.extend({
actions: {
animate() {
console.log('ok');
}
},
});
How to call animate() from my component ? What am I doing wrong ?
Changed the following code to this. Seems to be working.
<div>
{{yield this}}
</div>
{{#my-component as |mc|}}
<button {{action "doIt" target=mc}}>callDoIt</button>
{{/my-component}}

Global CRUD Ember.js

I was wondering if someone could give me brief direction. I'm making an app that I want to be able to take notes from anywhere I'm at in the app (CRUD). I'm rendering my presentations in my application controller using {{render}} but I'm not sure how to put the full crud operations there as well. This is what I have so far:
-- Presentation Controller
import Ember from 'ember';
var PresentationController = Ember.ObjectController.extend({
actions: {
edit: function () {
this.transitionToRoute('presentation.edit');
},
save: function () {
var presentation = this.get('model');
// this will tell Ember-Data to save/persist the new record
presentation.save();
// then transition to the current user
this.transitionToRoute('presentation', presentation);
},
delete: function () {
// this tells Ember-Data to delete the current user
this.get('model').deleteRecord();
this.get('model').save();
// then transition to the users route
this.transitionToRoute('presentations');
}
}
});
export default PresentationController;
-- Presentations Controller
import Ember from 'ember';
var PresentationsController = Ember.ArrayController.extend({
actions: {
sendMessage: function ( message ) {
if ( message !== '') {
console.log( message );
}
}
}
});
export default PresentationsController;
-- Model
import DS from 'ember-data';
var Presentation = DS.Model.extend({
title: DS.attr('string'),
note: DS.attr('string')
});
-- Presentations Route
import Ember from 'ember';
var PresentationsRoute = Ember.Route.extend({
model: function() {
return this.store.find('presentation');
}
});
export default PresentationsRoute;
-- Presentation Route
import Ember from 'ember';
var PresentationRoute = Ember.Route.extend({
model: function (params) {
return this.store.find('presentation', params.id);
}
});
export default PresentationRoute;
-- Application Route
import Ember from 'ember';
export default Ember.Route.extend({
model: function () {
return this.store.find('category');
},
setupController: function (controller, model) {
this._super(controller, model);
controller.set('product', this.store.find('product'));
controller.set('presentation', this.store.find('presentation'));
}
});
-- Application HBS
<section class="main-section">
<div id="main-content">
{{#link-to "presentations.create" class="create-btn expand" tagName="button"}} Add presentation {{/link-to}}
{{render 'presentations' presentation}}
{{outlet}}
</div>
</section>
-- Presentations HBS
{{#each presentation in controller}}
{{#link-to 'presentation' presentation tagName='li'}}
{{presentation.title}}
{{/link-to}}
{{/each}}
{{outlet}}
-- Presentation HBS
{{outlet}}
<div class="user-profile">
<h2>{{title}}</h2>
<p>{{note}}</p>
<div class="btn-group">
<button {{action "edit" }}>Edit</button>
<button {{action "delete" }}>Delete</button>
</div>
</div>
Basically what you're describing is a modal of sorts. It'll be accessible no matter what page (route) you're viewing, and you will be able to perform actions within this modal (creating notes, editing notes, deleting notes, etc) without leaving or affecting the current page being displayed in the background. Essentially, what this means is that you should leave the router alone, since the router is what controls the current page, and you don't want to affect that. You're not going to want to have any {{#link-to}} or transitionTo or transitionToRoute calls, nor any presentation-related routes or outlets.
Instead, you're going to have to handle everything at the controller and view level. This is where components really come in handy, as they're great for encapsulation if you use them correctly. Inside of presentations.hbs, I'd use components to represent each of the presentations:
{{#each presentation in controller}}
{{individual-presentation presentationModelBinding="presentation"}}
{{/each}}
Note that you'll need a corresponding IndividualPresentationComponent object that extends Ember.Component. Going further, inside of individual-presentation.hbs, I'd have code similar to what you have now, but with allowances for various CRUD operations:
{{#if editing}}
{{input value=presentationModel.title}}
{{textarea value=presentationModel.note}}
{{else}}
<h2>{{title}}</h2>
<p>{{note}}</p>
{{/if}}
<div class="btn-group">
{{#if editing}}
<button {{action "save" }}>Save</button>
{{else}}
<button {{action "edit" }}>Edit</button>
{{/if}}
<button {{action "delete" }}>Delete</button>
</div>
Note that the context for a component's template is the component itself, not some other controller. Similarly, actions fired inside of a component's template are direct to the component's actions hash. So your IndividualPresentationComponent will need to look like this somewhat:
IndividualPresentationComponent = Ember.Component.extend({
classNames: ['user-profile'],
actions: {
save: function () {
this.sendAction('save', this.get('presentationModel'));
this.set('editing', false);
},
edit: function () {
this.set('editing', true);
},
delete: function () {
this.sendAction('delete', this.get('presentationModel'));
}
}
});
Notice I'm using sendAction here. This is how components communicate with the outside world. To get this to work, go back your presentations.hbs and intercept the actions like so:
{{#each presentation in controller}}
{{individual-presentation presentationModelBinding="presentation"
save="savePresentation"
delete="deletePresentation"}}
{{/each}}
Here you're basically saying that if the component sends the "save" action, you want to handle it with your controller's "savePresentation" action, and if the component sends the "delete" action, you want to handle it with your controller's "deletePresentation" action. So your presentations-controller.js will need to implement those actions:
var PresentationsController = Ember.ArrayController.extend({
actions: {
savePresentation: function (presentationModel) {
...
},
deletePresentation: function (presentationModel) {
...
},
}
});
And you can delete PresentationController, since all of its functionality is now handled directly by your IndividualPresentationComponent and your PresentationsController.