0

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 %>
ecs
  • 708
  • 1
  • 14
  • 33

1 Answers1

0

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 } ) %>');
Zach Kemp
  • 11,736
  • 1
  • 32
  • 46
  • I should probably have said - I'm using a project show view to render the events - so you can create a new event, or edit an existing one, in the same page - it renders the partials here. I've pasted the javascript into the top of the project#show view for now (only for now!). So when I use what you have suggested, I am getting this error: 'undefined local variable or method `event' for #<#:0x4295c70>'. It is referring to the line 'form_for(event) do'. – ecs Oct 15 '12 at 21:03
  • How do I do the equivalent of this to call the partial?: <%= render :partial => "edit_events", :locals => { :event => @event } %> – ecs Oct 15 '12 at 21:05
  • I made an edit to `edit.js.erb` above. Let me know if that works with your form. – Zach Kemp Oct 15 '12 at 21:08
  • Unfortunately not, now I am getting this error: undefined method `model_name' for NilClass:Class. It is referring to this line: <%= form_for(event) do |f| %> which is in the form partial. Any ideas!? – ecs Oct 15 '12 at 21:13
  • Can you post your `edit` controller action and your event form partial? Are you able to render the edit action on its own (i.e., no javascript)? – Zach Kemp Oct 15 '12 at 21:16
  • Done - i've added everything. I can click the edit link next to the listed event, which takes me to the edit page for that event, yes, but surely I need the javascript to pass the id of the event to render the correct edit form below? Thanks for your help so far :) – ecs Oct 15 '12 at 21:26
  • I've tried it out without the javascript, and as I am getting the exact same error message, I'm guessing that does mean that the id of the event isn't getting passed to the render call? I don't know what to do to fix this!! – ecs Oct 15 '12 at 21:33
  • Yes, that's what `link_to "edit", edit_event_path(event) ... :remote => true` does - it calls the `edit` action for the current event, and renders the `edit.js.erb` template. What's in the `edit_events` partial? It seems like you're passing in a `nil` somewhere. – Zach Kemp Oct 15 '12 at 21:34
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18075/discussion-between-zach-kemp-and-emily-twist) – Zach Kemp Oct 15 '12 at 21:35
  • As I said, looks in the logs like this is finally working, but I can't actually test it as webrick has decided to have a holiday...! – ecs Oct 15 '12 at 21:59
  • You could try adding `gem 'thin'` to your gemfile, then start the server with `rails s thin`. No `webrick` required. – Zach Kemp Oct 15 '12 at 22:16
  • A restart seemed to be all it needed this time. And the code works great now, thanks for your help! – ecs Oct 15 '12 at 23:36