Struggling with rjs templates

Hi Oliver,

Oliver Oh wrote:

When clicking on a "Delete" button, nothing happens in the browser
unless I refresh, and then the item has gone (i have included the
:defaults js)
In the rails console, I see this:

ActionView::TemplateError (Called id for nil, which would mistakenly be
4 -- if you really wanted the id of nil, use object_id) on line #3 of
app/views/user/_pos.rhtml:
1: <ul>
2: <li>
3: <% form_remote_tag :url=>{:action=>:delete_pos,:id=>pos.id } do %>
4: <%= pos.posession_name %> - <%= submit_tag "Delete" %>
5: <% end %>
6: </li>

I can see that id=>pos.id is causing the problem, but not sure why.

My guess is that you're not actually assigning an id to the form which would explain why you're not seeing anything happen in the browser until you do a refresh. Get firebug and check out the DOM you're creating.

Best regards,
Bill

Hi Oliver,

Oliver Oh wrote:

Is it the form that needs an ID or the div that will have
its content replaced?

Depends on what you're trying to do and I'm not real sure from what you've
told us exactly what that is. In general, page.replace_html will treat the
DOM element with the id you pass in as a 'wrapper' and will replace
everything inside it with the content you specify via the partial.

I'm a little confused about your use of a single form inside the
posession_list. I'd expected to see you iterating through the collection in
your view. If you're wanting to use a button to trigger the delete on each
item, you could use a form to do it. Or you might want to check out
button_to_remote. Off the top, something like (untested)

<div id="posession_list">
  <% @posessions.each do |@this_posession| %>
     <%= render :partial=>"pos" %>
  <% end %>
</div>

And then in the partial use @this_posession.id to put an id on the element
you want to remove. But I'm assuming that removing the item from the view
is what you're trying to do. You'll need to say more, and show the relevant
controller code, for me to offer anything more concrete.

Best regards,
Bill

Bill Walton wrote:

Hi Oliver,

Oliver Oh wrote:

Is it the form that needs an ID or the div that will have
its content replaced?

Depends on what you're trying to do and I'm not real sure from what you've told us exactly what that is. In general, page.replace_html will treat the DOM element with the id you pass in as a 'wrapper' and will replace everything inside it with the content you specify via the partial.

I'm a little confused about your use of a single form inside the posession_list. I'd expected to see you iterating through the collection in your view. If you're wanting to use a button to trigger the delete on each item, you could use a form to do it. Or you might want to check out button_to_remote. Off the top, something like (untested)

<div id="posession_list">
  <% @posessions.each do |@this_posession| %>
     <%= render :partial=>"pos" %>
  <% end %>
</div>

And then in the partial use @this_posession.id to put an id on the element you want to remove. But I'm assuming that removing the item from the view is what you're trying to do. You'll need to say more, and show the relevant controller code, for me to offer anything more concrete.

I'd really discourage creating an instance variable and passing it down to the partial like this. You should consider using the locals hash in this instance. If you're using a partial, it's safe to assme that this partial is getting rendered somewhere else, correct?

I'd do something like this...

<div id="posession_list">
   <% @posessions.each do |posession| %>
      <%= render :partial=> "pos", :locals => { :posession => posession } %>
   <% end %>
</div>

Good luck!

Robby

Hi Robby,

Robby Russell wrote:

I'd really discourage creating an instance variable and
passing it down to the partial like this.

While I agree that passing a local to the partial is an option, I wonder why you'd discourage the use of an instance variable in this instance. We pass instance variables up from the controller to the view. Why not let them 'bubble up" from the main view to partials? He doesn't appear to be doing anything with it but setting a value to send back to an action. Looking forward to hearing your thoughts.

Best regards,
Bill

Bill Walton wrote:

Hi Robby,

Robby Russell wrote:

I'd really discourage creating an instance variable and
passing it down to the partial like this.

While I agree that passing a local to the partial is an option, I wonder why you'd discourage the use of an instance variable in this instance. We pass instance variables up from the controller to the view. Why not let them 'bubble up" from the main view to partials? He doesn't appear to be doing anything with it but setting a value to send back to an action. Looking forward to hearing your thoughts.

It's all about managing scope. After the block is finished, the instance variable still exists, which means something else in the view and/or controller can access it.

If it doesn't need to exist beyond that scope, there isn't any good reason to pass it down. If you have partials a few files deep and are relying on an instance variable, this would be discouraged. Think of your partials as somewhat like a method with parameters being passed. Right now, you're relying on variables that anything can access (and potentially update)... therefore, increasing the risk that someone might use the wrong instance variable in the wrong place or manner than it was originally intended.

Cheers,
Robby

Robby Russell wrote:

Bill Walton wrote:

Hi Robby,

Robby Russell wrote:

I'd really discourage creating an instance variable and
passing it down to the partial like this.

While I agree that passing a local to the partial is an option, I wonder why you'd discourage the use of an instance variable in this instance. We pass instance variables up from the controller to the view. Why not let them 'bubble up" from the main view to partials? He doesn't appear to be doing anything with it but setting a value to send back to an action. Looking forward to hearing your thoughts.

It's all about managing scope. After the block is finished, the instance variable still exists, which means something else in the view and/or controller can access it.

If it doesn't need to exist beyond that scope, there isn't any good reason to pass it down. If you have partials a few files deep and are relying on an instance variable, this would be discouraged. Think of your partials as somewhat like a method with parameters being passed. Right now, you're relying on variables that anything can access (and potentially update)... therefore, increasing the risk that someone might use the wrong instance variable in the wrong place or manner than it was originally intended.

I hit send too soon. :wink:

I also would discourage from EVER setting an instance variable within a view. There really isn't a good really for doing this at all. Views are not the place to do this, in my opinion.

Robby

Robby Russell wrote:

Robby Russell wrote:

Bill Walton wrote:

I also would discourage from EVER setting an instance variable within a view. There really isn't a good really for doing this at all. Views are not the place to do this, in my opinion.

That should have read... "There really isn't a good REASON for doing this at all."

...need some caffeine. :wink:

Hi Robby,

Robby Russell wrote:

It's all about managing scope.

Good explanation. I agree.

I also would discourage from EVER setting an instance
variable within a view. There really isn't a good reason
for doing this at all. Views are not the place to do this,
in my opinion.

I agree in here too. OTOH, I think it's sometimes a good idea to help folks
along in their learning in steps.

Best regards,
Bill