beeudoublez
beeudoublez

Reputation: 1242

Using Rails jQuery autocomplete when there is no model

jQuery autocomplete docs state there should be two Models, the first being the model that you want to use for autocomplete, the second being the model that has the first Model (and is attached to your page). However, I don't have the second model, just a Controller w/view that has form elements, one of them an autocomplete input of the first Model (Venue).

The docs say I should do

resources :parse do
get :autocomplete_venue_name, :on => :collection
end

But that won't work since the controller 'Parse' doesn't have a model. I tried making a static route but I need that :collection option. How can I work around this requirement?

EDIT: Below is the code from the rails+jquery autocomplete plugin. Note that I have a ProductsController but I don't have a Products model, so I can't do the routes.rb setup:

class Brand < ActiveRecord::Base end

MODEL TO SEARCH ON:

   create_table :brand do |t|
     t.column :name, :string
   end

CONTROLLER WITH DESIRED AUTOCOMPLETE FORM:

class ProductsController < Admin::BaseController
   autocomplete :brand, :name
end

ROUTES.RB

resources :products do
   get :autocomplete_brand_name, :on => :collection
end

This approach works only if I have a Products model, which I do not. I have a Controller that is displaying a form w/autocomplete inputs.

Upvotes: 2

Views: 653

Answers (1)

Kashiftufail
Kashiftufail

Reputation: 10885

I am using jquery multi auto complete plugin in which you can select one or multi auto

complete value and if there is no model then it will work e.g

$(document).ready(function() {

     var availableTags = [];
    <%@tags.each do |tag|%>
        availableTags.push('<%=tag.name%>');
    <%end%>

    $('#tags').multicomplete({
        source: availableTags
    });

});

in my case @tags = Tag.all

But you can give any other values in controller action.Whose model is not exist

Like in controller

@tags = ["cute","beauty","amazing"]

The code i am using for multi Autocomplete is below.

(function($, $a, $p) { // getting $p as a parameter doesn't require me to "var $p=..." and saves a two bytes ;-) ("var " versus ",x" in argument list [when minifier is shrinking variables])
    $p = $a.prototype;
    $.widget('ui.multicomplete', $a, {
        // Search for everything after the last "," instead of the whole input contents
        _search: function(value) {
            $p._search.call(this, value.match(/\s*([^,]*)\s*$/)[1]);
        },
        // Overwrite _trigger to make custom handling for events while still allowing user callbacks
        // Setting my own callbacks on this.options or binding using .bind() doesn't allow me to properly handle user callbacks, as this must be called AFTER the user callbacks are executed (which isn't possible by bind()ing when this.options[] is set)
        _trigger: function(type, event, data) {
            // call "real" triggers
            var ret = $p._trigger.apply(this, arguments);
            // When its select event, and user callback didn't return FALSE, do my handling and return false
            if (type == 'select' && ret !== false) {
                // When a selection is made, replace everything after the last "," with the selection instead of replacing everything
                var val = this.element.val();
                this.element.val(val.replace(/[^,]+$/, (val.indexOf(',') != -1 ? ' ' : '') + data.item.value + ', '));
                ret = false;
            }
            // Force false when its the focus event - parent should never set the value on focus
            return (type == 'focus' ? false : ret);
        },
        _create:function() {
            var self = this;
            // When menu item is selected and TAB is pressed focus should remain on current element to allow adding more values
            this.element.keydown(function(e) {
                self.menu.active && e.keyCode == $.ui.keyCode.TAB && e.preventDefault();
            });
            $p._create.call(this);
        },
        _initSource: function() {
            // Change the way arrays are handled by making autocomplete think the user sent his own source callback instead of an array
            // The way autocomplete is written doesn't allow me to do it in a prettier way :(
            if ($.isArray(this.options.source)) {
                var array = this.options.source, self = this;
                this.options.source = function(request, response) {
                    response(self.filter(array, request)); // Use our filter() and pass the entire request object so the filter can tell what's currently selected
                };
            }

            // call autocomplete._initSource to create this.source function according to user input
            $p._initSource.call(this);

            // Save a copy of current source() function, than new source() sets request.selected and delegate to original source
            var _source = this.source;
            this.source = function(request, response) {
                request.selected = this.element.val().split(/\s*,\s*/);
                request.selected.pop(); // don't include the term the user is currently writing as selected
                _source(request, response);
            };
            // TODO: instead of overwritting this.source, I can overwrite _search which is easier, but than I'll have to repeat jQuery-UI's code that might change
        },

        // Like $.ui.autocomplete.filter, but excludes items that are already selected
        filter: function(array, request) {
            return $.grep($a.filter(array, request.term), function(value) {
                return $.inArray(value, request.selected) == -1;
            });
        }
    });
})(jQuery, jQuery.ui.autocomplete);

But you should include some jquery auto complete js files from jquery.UI.Download files from there and include in project.

jquery.ui.core

jquery.ui.widget

jquery.ui.position

jquery.ui.autocomplete

Upvotes: 1

Related Questions