Posted by Tarential on March 19th, 2013 at 7:46am
Hi folks. Perhaps some of you are wondering where the next part of your AngularJS on Rails tutorial is, and with good reason. I missed last week and I apologize but it won't be out this week either. For the last six months I've been developing customer relationship management software for a startup I co-founded, 27 Volt Labs. This software, voltageCRM, is entering the beta stage.
For the first time we have people running real, production data on our software.
It's exciting. It's hectic. There are bugs, we fix them. There are new features people need, we implement them. There are blog posts that need to be written... but I fall behind. I must pick and choose my battles. I must needs choose my business over my blog. However, I will do my best to ensure that this state of chaos is short-lived and that the posts continue as scheduled.
For the second day in a row I'm up past 4am preparing for the users to hit the server at 6am. Last time I went to bed only to receive a call at quarter past six saying something needed to be changed. I think this time I'll just stay up and keep working.
All this and I still earn far less than minimum wage. So this is what it's like to be an entrepreneur.
Posted by Tarential on March 4th, 2013 at 1:42pm
After last week's post on retrieving data from your Rails API you should be able to view a list of tasks in your application. While an essential part of the client, seeing isn't everything. We need a way to create, update and delete tasks. Let's get started.
We'll be sending data using the same services we created last week for retrieving. Here they are in case you missed it:
Creating the Templates
To start with, create a form template containing fields for a task. In a slight deviation from traditional methods the name we give the input will not dictate which data is sent to the server by AngularJS. Instead, that association is made using the element's model. You're going to give each input field an attribute in the form of "data-ng-model" => "task.field_name". This binding works both ways; changing the input value will change task.field_name and changing task.field_name will change the input value.
As an added bonus, this binding will affect all other elements in the scope containing the same variable task. For a live preview box all you have to do is include your task show template in the same scope as your edit form. No more hitting the "preview" button and waiting for the server to respond. Everything is automated and live. However, there is something to watch out for.
Heads up: The DOM is not considered canon for data values. AngularJS stores values separately in memory.
This may seem like an irrelevant distinction since in most cases they actually match up. Certain elements, like select options, do not match. Their values instead are the indices for the options array. Don't be fooled when you inspect the DOM and don't assume that altering the DOM will change the AngularJS values. In addition, it's not necessary to create hidden input fields to pass variables along with the form. Simply set the value on the task object before you send it.
Here is an example of a form for a task object found in /templates/tasks/edit.html:
Here we have a template containing the task name and due date along with options to save, cancel or delete the task. The option to delete appears only if the task has an ID, indicating it is saved. This allows us to re-use the form for both creating new and editing existing tasks. How do we do that? The buttons still aren't functional! That's true. This code doesn't stand alone. We're going to update the index page from the previous post in order to add new tasks.
The first element is the new task button, followed by the task edit form. You'll only see one of the two at any given time since we hide/show them based on the same boolean flag.
Since we're planning to make changes to the existing tasks we'll want a way to update the task index without reloading the page. Add this function to your task controller (TaskController if you followed the previous post):
These templates aren't very useful by themselves. They require some controller updates to be made active. Start by adding the following functions to TaskController:
The new task function creates a new blank object and sets the editing flag to true while the cancel function simply sets the flag to false. The save function accepts the task model we've been editing and sends it to the server, whereupon the server replies with the generated ID. We add this ID to the task before inserting it into the top of the index.
"Wait," you say, "my server is throwing an error!" This is anticipated. We still need to set up the response format for the create method of our tasks controller on the Rails app:
Inserting this inside the respond_to do |format| block of your controller as outlined in the previous post will instruct the server to send the ID along with the success message. Now the client and server can speak to each other!
Earlier on I promised you the ability to edit tasks. Here's how. Add an edit button for each task on the show template (/templates/tasks/show.html):
Make it work by adding this function to your TaskController:
Finally, we'll need to add a destroyTask function and update the save function in the task controller as follows:
The new destroy function will tell the server to delete the given object. The save function has been modified to send an update command if the task has an ID (thus is already saved) or a create command otherwise. Afterwards they reload the task index to update the display.
There you have it folks! Some might consider this a complete client side web application, but there is still more left unwritten. Right now our app only responds to success. What happens when an API call fails or a requested update fails validation? We still need to handle error notification and fail gracefully. We also have to write our client side tests. Come back in two weeks to read more!