使用jQuery Autocomplete在Rails 4.0中动态创建和分配对象

时间:2014-02-05 07:02:10

标签: jquery ruby-on-rails autocomplete ruby-on-rails-4 nested-forms

我正在尝试使用自动完成功能构建一个表单,该表单将使用Rails 4在select上添加表单元素。 以下是模型(我使用的是MongoID):

class Ingredient
  include Mongoid::Document
  field :name
  field :unit
  has_many :recipe_ingredients, validate: false
end

class RecipeIngredient
  include Mongoid::Document
  field :quantity
  embedded_in :recipe
  belongs_to :ingredient
end

class Recipe
  include Mongoid::Document
  field :name
  embeds_many :recipe_ingredients
  accepts_nested_attributes_for :recipe_ingredients, allow_destroy: true
end

自动填写Coffeescript

jQuery ->
  $('#ingredients_search').autocomplete(
    source: (request, response) ->
            $.ajax( 
                url: "/ingredients.json",
                dataType: "json",
                data: request,
                success: (data) ->
                    response $.map data, (item) ->
                        label: item.name
                        value: item.name
                        _id: item._id
                        unit: item.unit
            )

    select: (event,ui) -> 
        $('#ingredients').append(ui.item.label)
);

搜索和使用自动完成工作正常,但我对如何动态创建RecipeIngredient对象以及为其分配配方和成分感到有点迷失。

我尝试过使用嵌套表单(http://railscasts.com/episodes/196-nested-model-form-revised?view=asciicast),但似乎无法让它正常工作。

任何指针都会有所帮助。

谢谢, 雷米

1 个答案:

答案 0 :(得分:0)

我想我终于搞定了!

诀窍是使用“html模板”在保留div(div.recipe)上添加数据属性,其余的我使用了Ryan Bates的视频(http://railscasts.com/episodes/403-dynamic-formshttp://railscasts.com/episodes/196-nested-model-form-revised)。< / p>

coffeescript:

jQuery->
    $('#ingredients_search').autocomplete(
    source: (request, response) ->
            #make our request and handle the response as normal
            $.ajax( 
                url: "/ingredients.json",
                dataType: "json",
                data: request,
                success: (data) ->
                    response $.map data, (item) ->
                        label: item.name
                        value: item.name
                        _id: item._id.$oid
                        unit: item.unit
        )
    select: (event,ui) ->
        myDiv = $('div.recipe')
        time = new Date().getTime()
        regexp = new RegExp(myDiv.data('id'), 'g')
        recipe_ingredient_div = myDiv.data('fields').replace(regexp, time)
        myDiv.append(recipe_ingredient_div)
        $("input[name='recipe[recipe_ingredients_attributes][" + time + "][ingredient_attributes][name]']").val(ui.item.label)
        $("input[name='recipe[recipe_ingredients_attributes][" + time + "][ingredient_attributes][id]']").val(ui.item._id)
    );

辅助方法:

module RecipesHelper
  def add_data_to_div(f, association)
    new_object = f.object.send(association).klass.new
    new_object.ingredient = Ingredient.new
    new_object.recipe = Recipe.new
    id = new_object.object_id
    fields = f.fields_for(association, new_object, child_index: id) do |builder|
      render(association.to_s.singularize + "_fields", f: builder)
    end
    return {id: id, fields: fields.gsub("\n", "")}
  end
end

成分偏:

<input type="text" id="ingredients_search" />
<%= content_tag_for(:div, f.object, data: add_data_to_div(f, :recipe_ingredients)) do %>
    <%= f.simple_fields_for :recipe_ingredients do |ingredient| %>
        <%= render 'recipe_ingredient_fields', :f => ingredient %>
    <% end %>
<% end %>

和recipe_ingredient_fields partial:

<%= content_tag_for(:fieldset, f.object) do %>
    <%= f.simple_fields_for :ingredient do |ingredient| %>
        <%= ingredient.input :name, disabled: true %>
        <%= ingredient.input :unit, disabled: true %>
        <%= ingredient.hidden_field :id %>
    <% end %>
    <%= f.simple_fields_for :recipe do |recipe| %>
        <%= recipe.hidden_field :id, :value => f.object.id %>
    <% end %>
    <%= f.input :quantity %>
    <%= f.hidden_field :_destroy %>
    <%= link_to '[remove]', '#', class: 'remove_fields' %>
<% end %>

编辑时我遇到了字段填写不正确的问题,但那是因为我错过了RecipeIngredient模型中的nested_attributes

belongs_to :recipe
accepts_nested_attributes_for :recipe, allow_destroy: true
belongs_to :ingredient
accepts_nested_attributes_for :ingredient, allow_destroy: true

希望这有帮助!

雷米