In the final episode of our 3-part series, we complete the CRUD operations with Create.
After that, we refactor the Create and Update operations (new and edit pages) with a helpful component- going farther than we did last year.
Links
- CRUD 2015
- CRUD 2016 parts 1 and 2
- github repo
Code
//router.js
Router.map(function() {
this.route('monsters', function(){
...
this.route('new')
})
});
//controllers/monsters/new.js
export default Ember.Controller.extend({
newModel: {},
actions: {
save(){
let model = this.store.createRecord('monster', this.get("newModel"))
this.set("newModel", {})
model.save().then(()=>{
this.transitionToRoute('monsters.monster.show', model)
})
}
}
})
//components/monster-form.js
export default Ember.Component.extend({
actions: {
save(){
this.attrs.save()
}
}
});
{{! templates/components/monster-form.hbs }}
<div class="monster-card">
Name: {{one-way-input value=model.name update=(action (mut model.name))}}
<br>
Level: {{one-way-input value=model.level update=(action (mut model.level))}}
<br>
<img src={{model.imageUrl}} />
<br>
Image Source: {{one-way-input value=model.imageUrl update=(action (mut model.imageUrl))}}
<br>
Price (in dollars): {{one-way-input value=model.price update=(action (mut model.price))}}
</div>
<button {{action 'save'}}>Save</button>
{{! templates/monsters/monster/edit.hbs }}
{{monster-form model=model save=(action "save")}}
{{! templates/monsters/new.hbs }}
{{monster-form model=newModel save=(action "save")}}
Transcript
Hey and welcome to the third and final part of our series on building a CRUD application in 2016 with Ember.
So we’re showing it, we show a list and individual ones, and then we can edit and destroy the monsters. However we also want a way to create monsters, and that’s what we’ll do today. We’ll also, after we create the initial version, we’ll find out how to use components in order to dry up some of our code.
So first we’ll go to our router and then we’ll add in a route for new
, and it’s going to be under monsters
. Then in our monsters handlebars, we’ll add a link. We’ll put it in the left side but above the list of monsters. The link will be to monsters.new
, and we’ll give it a tagName
of button
, so it looks like a button.
So if we go to the page and we click this, then you see we’ll be going to the new route, but there’s currently nothing showing there, so let’s make a handlebars template for that.
So we’ll nest that template under monsters, and then what we’re wanting is something very similar to the edit page. So we’ll go ahead and copy and paste it and we’ll change some things later, and then later in this episode we’ll dry it up with a component. But for now, here we are.
Now we need to make the new monsters controller. Once again, a lot of this can be copied from the edit
monster controller, but there are some important things we’ll need to change. So first of all there’s not a model there when it’s a new model, so we’ll create an empty hash as our new model. And here we’ll replace all instances of model
with newModel
, so that it’s using that.
Next, we'll need to create something, so we’ll create our model using the newModel
. So we’re creating a record that’s of type monster, and it has all the attributes that we’re setting here. And then we can save on this model that we’ve created, and then what we do looks very similar to what we were doing before.
So we can test whether this works fairly easily. So we’ll create our monster, and it works. But there is one problem. If we now hit ‘New Monster’, it will have saved all of that information because it’s still in the newModel
hash. So we’ll go ahead and set the newModel
to an empty hash whenever we’re saving it.
So we’ve got our ‘New Monster’ page working, but it does share a lot of code with the edit page, both in the controller but even more so in the handlebars. Look at this handlebars. Look at this handlebars. Very similar. So we’re going to combine that into a component that can be used by both new and edit.
So we’re going to generate a component and we’re going to call it monster-form
. So first we’ll grab everything from the edit
handlebars, except for the ‘Save’ button, and stick it in monster-form
. And then in edit
form we’ll put in a monster-form
component and feed it the model. In new
handlebars, we’ll be able to do something similar, but when we’re defining... when we’re putting in the monster-form
component, the model
will actually be newModel
instead of just model
.
So that’s where we left it last year, but we can now send down the action using closure actions, so we can set save
to the action save
, and we’ll be able to put this button in the monster-form
. We’ll go ahead and do the same thing with the edit
handlebars.
Then in monster-form.js
, we’ll need to add in our action, our save
action, and it’ll just call this.attrs.save
. And here we can see that it’s working just like before.
And it may not seem as if we've saved that much code, but if we had a more complex ‘Save’ button, this would definitely be a huge savings.
And there we go. Here is our basic CRUD app. We can create, we can show, we can edit, and we can destroy.
So if you’re watching this later in 2016, then you may already have new things like routable components or one-way components, the new Glimmer components. If so, don’t worry, this stuff is still valid, it just might be deprecated. And then in 2017, I’ll create a new version that’ll update with all that stuff. I’ll see you then.