Getting Started with Ember.js Part 4: Creating a New Car
In the last post, we set up a show and edit view. Let’s set up a view that allows for adding new cars.
Getting Started with Ember.js
- Part 1: Project Setup -> Github: one two three
- Part 2: The List View -> Github
- Part 3: Showing a Single Car -> Github
- Part 4: Creating a New Car -> Github
- Part 5: Deleting a Car and Wrapup -> Github
This is a very similar process to adding the show route. Start by adding a new route to app/assets/javascripts/router.js
. This time around we don’t have any parameters since this is a route that is creating and saving a new car.
Cars.Router.map(function() { this.resource("cars", function() { this.route('show', { path: '/:id' }); this.route('new'); }); });
Add a new route in app/assets/javascripts/routes/CarsRoutes.js
. The model for this route is a new car record. On save Ember Data will post to /cars
with a new car to create. Note that you also have to remove it from the client side store when leaving the page, otherwise you’ll end up with a blank car in the index grid. The call to rollback() in the deactivate function removes the car if the user decides to cancel. Once again you can transitionTo index or transitionTo the new car on the car.show route.
Cars.CarsNewRoute = Ember.Route.extend({ model: function() { return this.store.createRecord('car', {}); }, deactivate: function() { var model = this.modelFor(this.routeName) model.rollback(); }, actions: { save: function(model) { var self = this; model.save().then(function(response) { console.log('Success!'); //transition back to index //self.transitionTo('cars.index'); //transition to the saved new car self.transitionTo('cars.show', response); }).catch(function() { console.log('Failure!'); }); } } });
Finally, let’s add the template to app/assets/javascripts/templates/cars/new.js.hbs
. This template is the same as the show template. I’ll leave it up to you to remove the duplication.
<div id="cars-new" class="panel"> <h1>New Car</h1> <form {{action 'save' model on="submit"}}> <div class="row"> <div class="small-3 columns"> <label for="make" class="right inline required">Make</label> </div> <div class="small-9 columns"> {{input id="make" type="text" required="" value=make}} </div> </div> <div class="row"> <div class="small-3 columns"> <label for="model" class="right inline required">Model</label> </div> <div class="small-9 columns"> {{input id="model" type="text" required="" value=model.model}} </div> </div> <div class="row"> <div class="small-3 columns"> <label for="color" class="right inline required">Color</label> </div> <div class="small-9 columns"> {{input id="color" type="text" required="" value=color}} </div> </div> <div class="row"> <div class="small-3 columns"> <label for="condition" class="right inline required">Condition</label> </div> <div class="small-9 columns"> {{input id="condition" type="text" required="" value=condition}} </div> </div> <div class="actions"> <button type="submit" class="button success">Save</button> {{#link-to 'cars.index' class='button alert' }} Cancel {{/link-to}} </div> </form> </div>
Upon trying to save the new car, you’ll notice that Ember throws a 404 while trying to post to /cars.
We’ll have to head back over to the Rails side of things and set up a controller action to persist the new car.
Add a create method that saves the car and renders the new car’s JSON as a response. Once again, there is a fair bit of duplication here, so I’ll leave that up to you to solve. The controller in app/controllers/cars_controller.rb should look like this:
class CarsController < ApplicationController before_action :set_car, only: [:show, :update] def index respond_to do |format| format.json { render json: Car.all } end end def show respond_to do |format| format.json { render json: @car } end end def update respond_to do |format| if @car.update(car_params) format.json { render json: @car, status: :ok } else format.json { render json: @car.errors, status: :unprocessable_entity } end end end def create @car = Car.new(car_params) respond_to do |format| if @car.save format.json { render json: @car, status: :created } else format.json { render json: @car.errors, status: :unprocessable_entity } end end end private def set_car @car = Car.find(params[:id]) end def car_params params.require(:car).permit(:id, :make, :model, :color, :condition) end end
Finally, add an Add button to the index view in app/assets/javascripts/templates/cars/index.js.hbs
<div id="cars-index" class="panel"> <h1>Cars</h1> <table role="grid"> <thead> <tr> <th>Make</th> <th>Model</th> <th>Color</th> <th>Condition</th> </tr> </thead> <tbody> {{# each car in model}} <tr> <td>{{#link-to 'cars.show' car.id}} {{car.make}} {{/link-to}}</td> <td>{{car.model}}</td> <td>{{car.color}}</td> <td>{{car.condition}}</td> </tr> {{/each}} </tbody> </table> <div class="actions"> {{#link-to 'cars.new' class='button success' }} Add {{/link-to}} </div> </div>
Now that you’ve got the ability to save a new car, head on to the final post Part 5: Deleting a Car and Wrapup.
No Comments
No comments yet