Rails controller based javascript to keep your javascript outside of your views.
Based off Paul Irish's DOM-based Routing (or Garber-Irish Implementation). Works with turbolinks.
How it works
Jcontroller.create('users', {
html: {
// executes whenever users#index with html format is executed
index: function() {}
}
});No other code is needed.
Installation
Add gem 'jcontroller' to your application's Gemfile and run the bundle command, then add this to your app/assets/javascripts/application.js
//= require jcontroller
Controllers
Namespaces
Jcontroller creation and finding are based off the controller path.
// for Admin::UsersController
Jcontroller.create('admin/users', {});Filters
Jcontrollers can be created with before and after filters like so:
Jcontroller.create('users', {
html: {
// executes for all html format responses for UsersController, before the specific action
before: function() {},
// executes whenever users#index with html format is executed
index: function() {},
// executes for all html format responses for UsersController, after the specific action
after: function() {}
}
});Inheritance
By default, jcontrollers inherit from the application jcontroller and will execute it if it exists, such as:
Jcontroller.create('application', {
html: {
before: function() {},
index: function() {},
after: function() {}
}
});So with the jcontrollers above the order of execution is:
application.beforeusers.beforeapplication.indexusers.indexapplication.afterusers.after
You can also set your own inhertance chain:
Jcontroller.create('users', {
parent_path: 'users_base',
...
});API
- Parameters are accessed from
this.paramsor as the first parameter - The request state (controller_path, action_name, jcontroller, etc.) are also given in
this.stateor the second parameter - And other methods to work with jcontrollers
Jcontroller.create('users', {
html: {
index: function(params, state) {
//this.params === params
console.log(this.params);
//this.state === state
console.log(this.state);
var jcontroller = JController.find('application');
self.parent(); // === jcontroller
//excute application_jcontroller for this state and params again
jcontroller.execute_jaction(this.params, this.state);
//execute application_jcontroller html.index function
jcontroller.html.index();
}
}
});With ruby, you could also access the state in jaction to make action specific CSS:
<body data-controller="<%= jaction.controller_path %>" data-action="<%= jaction.action_name %>">
...
</body>Organization
I like having a jcontrollers directory and calling my files as jcontroller files (ex. users_jcontroller.js).
Parameters
Manual
Use the js method with the params option.
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
js { :params => { :id => @user.id } }
end
endFrom view template
You can also create parameters using a JSON DSL (such as jbuilder) by creating a template named <action_name>_params.js.<DSL suffix>:
# app/views/users/show_params.js.jbuilder
json.id @user.idControlling javascript execution
Stop
Stop all execution of all filters and methods for the action:
class UsersController < ApplicationController
def index
js false
end
endDifferent jcontroller
Execute a different jcontroller:
class UsersController < ApplicationController
def index
# same as "users#index.html", parameters and options are optional
js "users/show.html", { :params => { ... } }
end
endHTML view
Execute all filters and actions related to a action:
<!-- same as "users#index.html", parameters and options are optional -->
<%= execute_jaction "users/show.html", { :params => { ... } } %>Manually filter in Javascript
You can use the given state to stop execution of functions:
Jcontroller.create('application', {
html: {
before: function() {
if (this.state.action_name === 'destroy') { }
}
}
});Redirect
You can execute all filters and functions of the current action before the redirected action using:
class UsersController < ApplicationController
def index
js { :redirect => true }
redirect_to user_path(User.first)
end
endSo users/index.html will be executed before users/show.html.
Ajax
You can optionally execute jcontrollers for ajax instead of writing javascript in views by turning it in config/application.rb:
Jcontroller.ajax = trueJcontrollers will automatically execute with parameters given by the template with a JSON DSL:
# app/views/users/show.js.jbuilder
json.id @user.idCredits
Extracted out of Placemark. Originally called dom_routes. An alternative is paloma.