Search code examples
javascriptjqueryruby-on-railspartialrenderpartial

Using the id of a button to render a partial in Rails


I've got a view that displays a partial with a list of all the events a user has created, with an edit link next to it. What I want to happen is that when a user clicks 'edit', a form partial appears below so that you can edit that event.

For simplicity, I have managed to get the button's id to be the same as the event's id. So, what I want to happen is that when a button with an id of 2 is clicked, a form appears below to edit an event with an id of 2.

I think I need to make some sort of AJAX call to render a partial, but I don't know how to do this. Any help would be much appreciated, thanks.

All I have so far is (all the edit buttons have a class of btn-info):

$(document).ready(function(){
    $('.btn-info').click(function(e){
        e.preventDefault;
        var btnID = this.id;
        //something here to get the partial to render 
    });
}); 

Could I use something like the following to call the partial? I know this doesn't work, but may give some better idea of what I am trying to acheive:

$("#events").html("<%= escape_javascript render( edit_event_path(btnID) ) %>");

UPDATE: As requested, controllers & views:

Edit action on events controller:

def edit
    @event = Event.find(params[:id])

    respond_to do |format|
      format.html
      format.js
    end
end

Projects show view complete with pasted javascript:

<script>
    $(document).ready(function(){
    $('#new-event-button').click(function(e){
        e.preventDefault();
        $('#edit-events').hide();
        $('#delete-events').hide();
        $('#new-event').slideDown(function(){
            $('html, body').animate({
            scrollTop: $(document).height()-$(window).height()},200,"linear"
            );
        });
    });
    $('#edit-events-button').click(function(e){
        e.preventDefault();
        $('#new-event').hide();
        $('#delete-events').hide();
        $('#edit-events').slideDown(function(){
            $('html, body').animate({
            scrollTop: $(document).height()-$(window).height()},200,"linear"
            );
        });
    });
    $('#delete-events-button').click(function(e){
        e.preventDefault();
        $('#new-event').hide();
        $('#edit-events').hide();
        $('#delete-events').slideDown(function(){
            $('html, body').animate({
            scrollTop: $(document).height()-$(window).height()},200,"linear"
            );
        });
    });
    $('.btn-info').click(function(e){
        e.preventDefault;
        $('#events-forms').after('<%= escape_javascript( render :partial => "eventform", :locals => { :event => @event } ) %>');
    });
});

</script>

<div class="content-box timeline-box">
<div id="my-timeline"></div><br /><br />
<br />

<button id="new-event-button" class="btn btn-success btn-large">New Event</button>
<button id="edit-events-button" class="btn btn-info btn-large">Edit Events</button>
<button id="delete-events-button" class="btn btn-danger btn-large">Delete Events</button>

<div id="events-forms">
    <div id="new-event">
        <%= render :partial => "new_event", :locals => { :event => Event.new(:timeline_id=>@timeline.id) } %>
    </div>

    <div id="edit-events">
        <%= render :partial => "edit_events", :locals => { :events => current_user.events } %>  
    </div>

    <div id="delete-events">
        <%= render :partial => "delete_events", :locals => { :events => current_user.events } %>        
    </div>
</div>

And the form to edit an event ('_eventform.html.erb'):

<%= form_for(event) do |f| %>
  <% if event.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(event.errors.count, "error") %> prohibited this event from being saved:</h2>

      <ul>
      <% event.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <%=f.hidden_field 'timeline_id', :value => current_user.timeline.id %>
  <div class="field">
    <%= f.label :start_date %><br />
    <%= f.date_select :start_date %>
  </div>
  <div class="field">
    <%= f.label :headline %><br />
    <%= f.text_area :headline %>
  </div>
  <div class="field">
    <%= f.label :text %><br />
    <%= f.text_area :text %>
  </div>
  <div class="field">
    <%= f.label :media %><br />
    <%= f.text_area :media %>
  </div>
  <div class="field">
    <%= f.label :caption %><br />
    <%= f.text_area :caption %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Solution

  • Here's what I would do in the list partial:

    <% @events.each do |event| %>
       <div id="event_<%= event.id">
          #... whatever event display code you use
          <%= link_to "edit", edit_event_path(event), :class => '.btn-info', :remote => true %>
       </div>
    <% end %>
    

    In your controller:

    class EventsController < ApplicationController
    
      def edit
        @event = Event.find(params[:id])
        #.. whatever else you currently have here
    
        respond_to do |format|
          format.html
          format.js
        end
      end
    
    end
    

    Then, in a new view (app/views/events/edit.js.erb):

    $('#event_<%= @event.id %>').after('<%= escape_javascript( render :partial => "edit_events", :locals => { :event => @event } ) %>');