Skip to content

Rails gem providing modal based ajax CRUD and scaffolding for jQuery & Bootstrap powered applications. Uses bootbox.js

Notifications You must be signed in to change notification settings

jkaipr/bootbox_crud

Repository files navigation

Build Status

Bootbox modal CRUD

Provides Rails modal CRUD scaffolding powered by bootstrap & bootbox & simple_form. Built for use with Turbolinks, jQuery and Twitter Bootstrap 3.

Screenshots

This is what you get after running rails g model Block name width:integer height:integer depth:integer with this gem setup in your rails application.

All modal views are using AJAX and template partials, which makes it behave faster compared to full page reloads.

Makes it easy to open up a modal for selected action and model on click by setting data attributes to HTML tags, no additional javascript needed.

Initial setup

Set custom scaffolding generators in your config/application.rb

config.generators do |g|
  g.template_engine :haml_modal_crud
  g.resource_route  :modal_crud_route
end

Require the main javascript file in your app/assets/javascripts/application.js

//= require bootbox_crud_main

Require the main stylesheet file in your app/assets/stylesheets/application.css and also don't forget to add the main Bootstrap stylesheet

*= require bootstrap
*= require bootbox_crud_main

Add bootbox alert markup into the main container of your app/views/layouts/application.html.haml

%body
  .container
    = yield
    = bb_alert

Run the install generator to copy over default simple_form initializers and models.js for defining modal CRUD enabled models

$ bundle exec rails g bootbox_crud:install

Scaffolding

Custom model scaffolding is enabled by installing and configuring this gem. The generated files are following the rules described in the Modal CRUD section.

 $ bundle exec rails g scaffold Block name width:integer height:integer depth:integer

The above code will give you a ready to use, nicely formatted modal enabled Block CRUD. Just migrate the DB.

Modal CRUD with bootbox.js

This concept is a work in progress and suggestions are welcome.

Main source files are in the gem:

vendor/assets/javascripts/bootbox_crud_modals.js
app/views/modals/_form.js
app/views/modals/_alert.js
app/views/modals/_create.js
app/views/modals/_destroy.js
app/views/modals/_update.js

and in your application

app/assets/javascripts/models.js

Controller

Create, update and destroy

All of these methods must have a js response format defined in the respond_to block. Update example:

respond_to do |format|
  if @model.update(model_params)
      ...
      format.js
    else
      ...
      format.js
    end
  end
end

New, edit and show

If you want your modals to be fast, related actions shouldn't render with a full layout. Instead return only the form or detail template. In another words, use render layout: false.

def new
  @model = Model.new

  respond_to do |format|
    format.html { render layout: false }
    format.json { render json: @model }
  end
end

def edit
  render layout: false
end

Different show view template for modal and normal page

In cases where a separate view template is needed for modal and normal full page show action, you can achieve that by doing the following. The modal show request accepted content type is */* so it is going to take the .js format response option as acceptable, because it is the first in the list. A standard request will skip format.js and take the html option.

def show
  respond_to do |format|
    format.js { render 'show_modal', layout: false }
    format.html
  end
end

This method can also be used for differentiating edit and new actions for modal and normal views.

Views

Create, update and destroy

Three new files have to be added to the views directory of the related model:

create.js.erb

<%= render partial: 'modals/create', locals: { model: @model, form_path: 'model/form' } %>

update.js.erb

<%= render partial: 'modals/update', locals: { model: @model, form_path: 'model/form' } %>

destroy.js.erb

<%= render partial: 'modals/destroy', locals: { model: @model, form_path: 'model/form' } %>

The partials in app/views/modals directory should provide the necessary functionality for most cases. If you need some special behaviour, implement it instead of rendering the partial.

Create/Destroy visit_path [optional parameter]: determines what page to load after the model has been created/destroyed.

The path is visited by invoking Turbolinks.visit(visit_path). If it isn't set, the current page will be reloaded.

It is mostly useful in cases:

  • when you create a new model and want to redirect to its full page detail or when you create a new subpage/tab and you want to refresh the page with an anchor after the base URL (the example is used for overviews)

    <%= render partial: 'modals/create', locals: { model: @overview, form_path: 'overviews/form', visit_path: "#overview_#{@overview.id}" } %>

  • where you can delete a model from its full page detail and you need to redirect the user to some list view, a simple page reload wouldn't be useful because the model was destroyed and its detail can't be shown anymore

    <%= render partial: 'modals/destroy', locals: { visit_path: "/#{ location_name.to_s }/unipolars" } %>

New, edit and show

All views being shown inside a modal window must have a root node with id='content'. Example in haml:

#content
  = render 'form'

The javascript handling the response will fill this node and its contents into the modal window body.

Forms

Forms used inside of modal windows need to have the remote attribute set to true.

= simple_form @model, remote: true

This way they are submitted via an ajax request.

The ApplicationHelper#remote_form_options helper with default simple_form formatting and layout wrapping options should be used instead of only writing remote: true to keep all forms unified. But more on that in the main forms section of this readme.

Show helpers

Use these in case you want to show values of a model in a modal window.

show_value(label, value)
show_link_to(label, object, link_text)
show_link_to_array(label, objects, name_object_field)

show_value 'Name', @model.name
show_link_to 'Model', @model, @model.name
show_link_to_array 'Model blackboxes', @model.blackboxes, 'name'

Wrap them into a div with class='form-horizontal'. Bootstrap horizontal form layout with little customization is used to display the values.

Adding class='show' to root node with id='content' is mandatory to get the right styling. If you forget this one, it will look like input fields.

#content.show
  .form-horizontal
    = show_value 'Name', @model.name
    = show_value 'Status', @model.status

Links to modals

Making links modal enabled is done via data attributes.

data-entity='Model'
data-action='edit'
data-id='1'

In haml:

= link_to '#', :class => 'btn btn-primary btn-sm', data: { id: @model.id, entity: 'Model', action: 'edit' } do
  %i.fa.fa-edit
  edit

There is a global button handler searching for any DOM nodes with 'data-entity' attribute. Click events of such nodes lead to modals. The logic is simple, clicking on a node with the above values will lead to this function invocation:

BBCrud.Model.edit({id: 1})

Available actions are:

  • new
  • edit
  • show

Adding a new model to modals on the client side

The above mentioned functions are defined in models.js, if you want to add modals to a new model, you have to add a new line there.

BBCrud.Models.add(namespace, baseUrl, modalHeaderTitle);
  • namespace is used to define the BBCrud.Unipolar object
  • baseUrl is setting the base route for the models actions
  • modalHeaderTitle is used in modal titles, it should be a singular downcase name of the model

Filled in for unipolars:

BBCrud.Models.add('Unipolar', '/unipolars/', 'unipolar');

The above function invocation creates these functions:

BBCrud.Models.Unipolar.new
BBCrud.Models.Unipolar.edit
BBCrud.Models.Unipolar.show

Now you should be all set to click your data-entity links and call the functions from your scripts if needed.

Note: I18n is currently not supported on the client, there are a few ways how to approach it. The necessary changes should be simple.

Adding custom actions to models (non CRUD)

Is done in models.js by adding a line similar to the for defining CRUD actions. Here is an example for close event action:

BBCrud.Models.addAction('Event', '/events/', 'event', 'close');

The first three arguments are the same as for BBCrud.Models.add function, the last argument is the new action name. After adding this line, you can create a button with the following data attributes and your modal is almost ready.

data-entity='Event'
data-action='close'
data-id='1'

Of course you have to do all the little tweaks on this action, as you did for CRUD. Meaning, adding #content to the form view and rendering it without layout. Next adding format.js to the relevant controller action and creating a *.js.erb view template for it.

To finish our Event.close example, the file will be named events/close_event.js.erb and it's contents:

<%= render partial: 'modals/form', locals: { model: @event, form_path: 'events/close', success_alert: 'Closed' , error_alert: 'Error while closing' } %>

The important detail to notice is the use of modals/form partial, which was made to handle custom actions. The rest of the arguments are self-explanatory.

Modals in short

  • Create format.js lines in respond_to block of controller :create, :update, :destroy
  • Return views without layout in controller :new, :show, :edit
  • Make sure your views have a root id='content' node & with class='show' in case of a show view using show helpers from this guide
  • Make sure your form has remote: true or preferably remote_form_options with simple_form, the layout should be the same as in the example in form section of this README
  • Add create, update and destroy .js.erb files to the view directory and fill them according to this guide
  • Add your model definition as a new line to models.js
  • Add data-entity, data-action and data-id with the right values to an element on the page and click it, or call BBCrud.Models.ModelName.new/edit/show() from your javascript to show the modal

Custom scaffold source files

If you want have a peek or override some of the scaffolding templates, here is an overview of the files used:

haml_modal_crud

lib/generators/rails/haml_modal_crud/templates/create.js.erb
lib/generators/rails/haml_modal_crud/templates/destroy.js.erb
lib/generators/rails/haml_modal_crud/templates/update.js.erb
lib/generators/rails/haml_modal_crud/haml_modal_crud_generator.rb
lib/generators/rails/haml_modal_crud/USAGE

modal_crud_route

lib/generators/rails/modal_crud_route/modal_crud_route_generator.rb

haml scaffold templates override

lib/templates/haml/scaffold/_form.html.haml
lib/templates/haml/scaffold/edit.html.haml
lib/templates/haml/scaffold/index.html.haml
lib/templates/haml/scaffold/new.html.haml
lib/templates/haml/scaffold/show.html.haml

controller scaffold template override

lib/templates/rails/scaffold_controller/controller.rb

Changelog

0.2.0 - some breaking changes

  • defined model actions moved to BBCrud.Models., declaring them directly on BBCrud. was dangerous, new models could overwrite basic functionality [Models, Modals, Alert]
  • renamed actions on models to new, edit, show [previously was create, update, show]
  • added a few more jasmine specs

TODOs

  • I18n support on client side
  • Improve BBCrud.Alert / integration with Rails flash messages

About

Rails gem providing modal based ajax CRUD and scaffolding for jQuery & Bootstrap powered applications. Uses bootbox.js

Resources

Stars

Watchers

Forks

Packages

No packages published