Rails, AngularJS and jQuery_ujs

Unobtrusive JavaScripts plays well with AngularJS

Lost in Space
@tomchentw/software
2 min readJun 30, 2014

--

In the previous post I talked about handling AngularJS CSRF configuration in Rails. But still left one question unresolved, that’s how to make Unobtrusive JavaScripts(UJS) still runs well in AngularJS + Rails environment but without jQuery dependency?

Unobtrusive JavaScripts

First, in rails world, UJS is done by the gem (with javascript assets) called jquery_ujs. It integrated with Rails so well so we’re easily to ignore it. What does it do? Basically when you write:

ul
li= link_to ‘Sign Out’, destroy_user_session_path, method: :delete

somewhere of navigation bar, and it will translate to the html:

<ul>
<li><a href=”/users/sign_out”, data-method=”delete”>Sign Out</a></li>
</ul>

Notice the data-method attribute? It allows user to issue a http DELETE request when user click on the “Sign Out” link, making it simple to deal with a RESTful api.

You can found a typical, real world example on the RubyGems official site:

Unobtrusive Scripting

This technique is so called unobtrusive scripting: using data-attribute to create zero config extra behavior. You can read more on this in the wiki page of jquery_ujs.

However, as its name shows, jquery_ujs depends on jQuery, which is a great library for Document-Based web page. While we’re using angularjs to create Component-Based web app, the removal of jQuery dependency arises. And I planed to write a plugin to replace jquery_ujs after reading it’s source codes.

angular_ujs

It’s also released as a ruby gem, so you can easily use it with Rails and Assets Pipeline (just like jquery_ujs does).

It supports the following features:

1. data-method 2. data-remote (require extra config in angular controllers/htmls) 3. data-confirm

To prevent these directive pollute non-Rails generated attributes, such as form’s method attribute, we’ll check on the element to make sure the attribute is declared with data- prefix before link state of directive.

Form Elements

With data-remote, we want to submit the form with ajax. But angular don’t know how to serialize the form into a json object (there’s no equlvalent $.fn.serializeArray). However, the angular way has already solve this problem with ngModel!!!

For those data you want to send to backend, just give them an ng-model directive. You can bound them to a object and assign the object name as the value of data-remote (As we shown below).

<form accept-charset=”UTF-8" action=”/contact_me” data-remote=”contact” method=”post”>
<input ng-model=”contact.first_name” required=”required” type=”text”>
<input ng-model=”contact.email” required=”required” type=”email”>
<input name=”commit” type=”submit” value=”Submit”>
</form>

Same API, Same Functionalities

We can definitely support all three logic into one element:

<a href=”/confirm” data-confirm=”Are u sure?” data-method=”PUT” data-remote=”true”>

So that it will issue a http PUT ajax request to server when the user click the link and confirm the popup dialog.

Wish you have a nice day with angular_ujs.

--

--

Lost in Space
@tomchentw/software

<Tom Chen> Aspie. Introvert. Remoter. Blogger. 「從程式碼的26個英文字母到文章的26個英文字母,開始發現寫作的魅力。」