Module: TokenField::FormBuilder
- Includes:
- ActionView::Helpers
- Defined in:
- lib/token_field/form_builder.rb
Instance Method Summary collapse
-
#token_field(attribute_name, options = {}) ⇒ Object
form_for helper for token input with jquery token input plugin for has_many and belongs_to association.
Instance Method Details
#token_field(attribute_name, options = {}) ⇒ Object
form_for helper for token input with jquery token input plugin for has_many and belongs_to association
railscasts.com/episodes/258-token-fields loopj.com/jquery-tokeninput/
helper will render standard text field input with javascript. javascript will change standard input to token field input
EXAMPLE
class Category < ActiveRecord::Base
attr_accessible :name, :parent_id, :product_ids
has_many :products
# method for converting array of categories to array of hashes in format that token input accepts
def self.token_json(items)
items.map{|i| {:id => i.id, :name => i.name} }
end
end
class Product < ActiveRecord::Base
attr_accessible :name, :category_id
belongs_to :category
end
class CategoriesController < ApplicationController
# action for autocomplete
def token
@categories = Category.where("categories.name like ?", "%#{params[:q]}%")
respond_to do |format|
format.json { render :json => Category.token_json(@categories) }
end
end
# rest of the class
end
then in routes add route for token ajax call
MyApplication::Application.routes.draw do
resources :categories do
collection do
get :token # route for token -> token_categories_path
end
end
end
then in view we call token_field token_field input will be default expects, that Category model exists <%= form_for @product do |f| %>
<%= f.token_field :category_id %>
<% end %>
possible options:
in case the association roles where given like this
class Product < ActiveRecord::Base
belongs_to :cat, :class_name => 'Category', :foreign_key => :cat_id
end
then right model need to be specified
<%= f.token_field :cat_id, :model => :category %>
We can use token_input also for mapping category to products we will use ActiveRecord method product_ids which be default return array of ids from association <%= form_for @category do |f| %>
<%= f.token_field :product_ids %>
<% end %>
in model we have to change product_ids= method like this
class Category < ActiveRecord::Base
has_many :products
alias_method :product_ids_old=, :product_ids=
def product_ids=(ids)
ids = ids.split(",").map(&:to_i) if ids.is_a?(String)
self.product_ids_old=ids
end
# rest of the class...
end
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/token_field/form_builder.rb', line 93 def token_field(attribute_name, = {}) association_type = @object.send(attribute_name).respond_to?(:each) ? :many : :one model_name = ([:model] || attribute_name.to_s.gsub(/_ids?/, "")).to_s association = attribute_name.to_s.gsub(/_ids?/, "").to_sym model = model_name.camelize.constantize token_url = [:token_url] append_to_id = [:append_to_id] token_limit = nil token_limit = 1 if association_type == :one if token_url.nil? token_url = "/#{model_name.pluralize}/token.json" end id = @object.send(:id) html_id = "#{@object_name}_#{attribute_name.to_s}" if append_to_id == :id && id html_id << "_#{id}" elsif append_to_id && append_to_id != :id html_id << "_#{append_to_id}" end html_id = html_id.parameterize.underscore value = nil data_pre = nil if association_type == :one && @object.send(association) data_pre = model.token_json([@object.send(association)]).to_json() value = @object.send(association).id elsif association_type == :many && @object.send(association.to_s.pluralize).count > 0 data_pre = model.token_json(@object.send(association.to_s.pluralize)).to_json() value = @object.send(attribute_name).join(",") end on_add = [:on_add] ? "#{[:on_add]}" : "false" on_delete = [:on_delete] ? "#{[:on_delete]}" : "false" js_content = " jQuery.noConflict(); jQuery(function() { jQuery('##{html_id}').tokenInput('#{token_url}', { crossDomain: false, tokenLimit: #{token_limit.nil? ? "null" : token_limit.to_i}, preventDuplicates: true, prePopulate: jQuery('##{attribute_name}').data('pre'), theme: 'facebook', hintText: '"+t('helpers.token_field.hint_text')+"', searchingText: '"+t('helpers.token_field.searching_text')+"', noResultsText: '"+t('helpers.token_field.no_results_text')+"', onAdd: "+on_add+", onDelete: "+on_delete+" }); }); " script = content_tag(:script, js_content.html_safe, :type => Mime::JS) text_field("#{attribute_name}", "data-pre" => data_pre, :value => value, :id => html_id) + script end |