2016-10-13 3 views
0

Я пытаюсь создать форму, которая будет генерировать копии вложенной формы в зависимости от выбора пользователя. У меня есть 3 модели: визуализации, у которых has_many Rows, у которых has_many Panes.Динамически генерировать копии частичной формы на основе выбора пользователя во вложенной форме

Я хочу, чтобы пользователь мог щелкнуть небольшое раскрывающееся меню, которое будет генерировать строку, а затем выбрать 1, 2 или 3 панели. В зависимости от их выбора это создаст форму своего выбора из рендера.

here is an example where a user chose 3 panes (3 upload boxes for images) with just styled divs in place of the form

Для начала. Я знаю, что мне нужно немного изменить мой контроллер, но я не уверен, как это сделать с вложенной формой, поскольку в каждом примере, который я видел до сих пор, вам нужно предопределить, сколько раз вы «строили», вложенная модель (не уверен, что это правильная терминология). Я не уверен, как сделать эту часть динамичной.

Вот что я имею в виду:

//visualization_controller.rb 
 

 
def new 
 
    @visualization = Visualization.new 
 
    rows = @visualization.rows.build 
 
    panes = rows.panes.build 
 
    end

здесь является примером визуализации, который будет вызываться, если USR хотите сгенерировать строку только с 1 панели:

<div class="medium-12 columns one_box_wrapper first" style="display:none"> 
 
    <%= f.fields_for :rows, Row.new do |r| %> 
 
    <%= r.label :rowtitle %> 
 
    <%= r.text_field :rowtitle %> 
 
    <div class="nested" style="display:inline-block"> 
 
      <%= r.fields_for :panes, Pane.new do |p| %> 
 
      <%= p.label :text %> 
 
      <%= p.text_field :text %> 
 
      <div class="mehv"> 
 
       <img id="img_prev" width=300 height=300 src="#" alt="your image" class="img-thumbnail hidden"/> <br/> 
 
       <span class="meh"> 
 
       Upload Pane Image<%= p.file_field :pane_photo, id: "pane_photo" %> 
 
       </span> 
 
       <%= p.hidden_field :pane_photo_cache %> 
 
      </div> 
 
      <% end %> 
 
     </ul> 
 
    </div> 
 
    <% end %> 
 
    </div>

Возможно ли это в рельсах? Я чувствую, что javascript вступает в игру, но я не думаю, что вам разрешено передавать серверный код через JS.

Я чувствую себя немного над головой с этим, и любая помощь будет принята с благодарностью!

EDIT

Я закончил с использованием кокон камень, как это, кажется, сделал мою жизнь намного проще, однако .. я не могу получить визуализации для отображения всех на главной странице! Я не уверен, в чем проблема. Название и изображение обложки отображаются, но ничего больше!

//schema.rb 
 

 
    create_table "panes", force: :cascade do |t| 
 
    t.integer "row_id",  null: false 
 
    t.text "text" 
 
    t.string "pane_photo" 
 
    end 
 

 
    create_table "rows", force: :cascade do |t| 
 
    t.integer "visualization_id", null: false 
 
    t.string "rowtitle" 
 
    end 
 

 
    create_table "visualizations", force: :cascade do |t| 
 
    t.string "title",  null: false 
 
    t.string "cover_image" 
 
    end

//controller.rb 
 

 
class VisualizationsController < ApplicationController 
 
    before_action :authenticate_user!, except: [:index, :show] 
 
    before_action :authorize_user, except: [:index, :show] 
 
    helper_method :resource 
 

 
    def index 
 
    @visualizations = Visualization.all 
 
    @visualization = Visualization.new 
 
    end 
 

 
    def new 
 
    @visualization = Visualization.new 
 
    rows = @visualization.rows.build 
 
    panes = rows.panes.build 
 
    end 
 

 
    def create 
 
    @visualization = Visualization.new(visualization_params) 
 

 
    if @visualization.save 
 
     redirect_to edit_visualization_path(@visualization) 
 
    else 
 
     render :new 
 
    end 
 
    end 
 

 
    def edit 
 
    @visualizations = Visualization.all 
 
    @visualization = Visualization.find(params[:id]) 
 
    end 
 

 
    protected 
 

 
    def visualization_params 
 
    params.require(:visualization).permit(:title, :cover_image, rows_attributes: [:visualization_id, :rowtitle, panes_attributes:[:text, :pane_photo]]) 
 
    end

//index.html 
 

 
<div class="visual_wrap text-center"> 
 
    <ul class="no-bullet text-center"> 
 
    <% @visualizations.each do |visualization| %> 
 
    <li class="text-center"> 
 
     <div class="row visualization text-center"> 
 
     <%= image_tag visualization.cover_image.to_s, id: "visualization_image", class: "output_image" %> 
 
     <p class="visualization_title"><%= visualization.title %></p> 
 
     <a href="#" id="visualization_link"><p>+</p></a> 
 
     </div> 
 
     <div class="placeholder"> 
 
     <% visualization.rows.each do |row| %> 
 
      <%= row.rowtitle %> 
 
      <% row.panes.each do |p| %> 
 
       <%= p.text %> 
 
       <%= image_tag p.pane_photo.to_s, id: "pane_image", class: "output_image" %> 
 
      <% end %> 
 
     <% end %> 
 
     </div> 
 
    </li> 
 
    <% end %> 
 
    </ul> 
 
</div>

//new.html.erb 
 

 
<% if user_signed_in? %> 
 
<% if current_user.admin? %> 
 
<div class="try"> 
 
    <div class="breadcrumb-wrapper"> 
 
    <ul class="breadcrumbs"> 
 
     <%= form_for @visualization, :html => {:multipart => true} do |f| %> 
 
     <li><a href="#" class="preview button secondary">Preview</a></li> 
 
     <li><div class="separating-bar">|</div> 
 
     <li><input type="submit" name="commit" value="Save" class="save button secondary"></li> 
 
     </ul> 
 
    </div> 
 
    <div class="cover_image text-center"> 
 
     <div class="row pre_img_prev"> 
 
     <div class="gray_bar"></div> 
 
     <div class="img_prev"> 
 
      <img id="img_preview" src="#" alt="your image" class="img-thumbnail hidden text-center"/> 
 
      <input type="text" name="visualization[title]" id="visualization[title]" class="inputtext" /> 
 
      <label for="visualization[title]" id="text_preview">+ Add Title</label> 
 
      <div class="trash-can_title"> 
 
      <a href="#" id="trash-can_title"><i class="fa fa-trash fa-3x" aria-hidden="true"></i></a> 
 
      </div> 
 
     </div> 
 
     <input type="file" name="visualization[cover_image]" id="visualization_cover_image" class="inputfile" /> 
 
     <label for="visualization_cover_image">+ Add Cover Image</label> 
 
     <%= f.hidden_field :cover_image_cache %> 
 
     <div class="trash-can_cover"> 
 
      <a href="#" id="trash-can_cover"><i class="fa fa-trash fa-3x" aria-hidden="true"></i></a> 
 
     </div> 
 
     </div> 
 
    </div> 
 
    <div class="row linkstest"> 
 
    <div class="rows"> 
 
     <%= f.fields_for :rows, Row.new do |task| %> 
 
     <%= render 'row_fields', f: task %> 
 
     <% end %> 
 
     <div class="links"> 
 
     <%= link_to_add_association "Add Row", f, :rows %> 
 
     </div> 
 
    </div> 
 
    <% end %> 
 
    <% end %> 
 
    <% end %> 
 
    </div> 
 
    </div>

ответ

0

Вам не нужно действительно JS, за исключением того, чтобы сделать его более «быстрым». Я думаю, что вы ищете вложенные формы.

Взгляните на RaisCast, это немного устарело, но это хороший фундамент.

Возможно, вы захотите изучить Cocoon gem, чтобы помочь вам создать новые поля динамически.

Rails nested_form inside nested_form

Update

Если вы не хотите использовать JavaScript, вообще, что вам нужно сделать дополнительный запрос к контроллеру, чтобы сказать, что для инициализации (построить) строки и стекла для вас, чтобы он отображал пустые поля в представлении. Например:

def new 
    @visualization = Visualization.new 
    num_rows = params[:num_rows] 
    num_rows.each { @visualization.rows.build } 
end 

Вы также должны были бы иметь количество стекол в каждой строке, так что параметр должен быть внутри атрибутов в строке, например, params[:visualization][:rows][0][:num_panes], и используя этот параметр, вы инициализируете панели в строке. Вероятно, лучше всего поставить эту логику в сервисе Factory.

Однако, если вы создаете пустые поля с помощью JS, вы можете избавиться от этого дополнительного запроса и всей этой логики. Это происходит потому, что Rails будет автоматически инициализировать (построить) строки и панели, если вы даете ему правильные атрибуты, такие как:

{ 
    visualization: { 
    rows_attributes: { 
     # These are the attributes from an existing record 
     0: { 
     id: 39, 
     panes_attributes: { 
      0: { 
      id: 992 
      } 
     } 
     }, 
     # This is a new set of attributes for a new record 
     # passed by the fields generated by cocoon where xxx 
     # and yyy are random numbers 
     xxxx: { 
     panes_attributes: { 
      yyyy: { 
      } 
     } 
     } 
    } 
    } 
} 

Тогда все, что вам нужно сделать в вашем контроллере:

def new 
    # visualization_params are the permitted attributes 
    @visualization = Visualization.new(visualization_params) 
end 
+0

I действительно смотрел на это и рассматриваю это. Может быть, только по созданию моей визуализации, перенаправляйте на редактирование страницы, чтобы добавить строки? – scotchpasta

+0

К сожалению, мой комментарий не закончился. Я хотел спросить, почему мне не нужен JS? Как я смогу сделать новое поле без него? Кокон управляет этим? – scotchpasta

+0

Обновленный мой ответ, может занять некоторое время, чтобы получить одобрение, надеясь, что это поможет. – guzart

Смежные вопросы