mbigras
mbigras

Reputation: 8055

Rendering collection partial

From the Using Ajax and jQuery in Rails 5 Apps tutorial (the project can be found at bparanj/ckl) and given the following view and partial:

app/views/tasks/index.html.erb:

<h1>Task Dog</h1>

<%= link_to "New Task", new_task_path, id: "new_link" %>

<h2>Incomplete Tasks</h2>
<div class="tasks" id="incomplete_tasks">
  <%= render @incomplete_tasks %>
</div>

<h2>Complete Tasks</h2>
<div class="tasks" id="complete_tasks">
  <%= render @complete_tasks %>
</div>

app/views/tasks/_task.html.erb:

<%= form_for task do |f| %>
  <%= f.check_box :complete %>
  <%= f.submit "Update" %>
  <%= f.label :complete, task.name %>
  <%= link_to "(remove)", task, method: :delete, data: {confirm: "Are you sure?"} %>
<% end %>

The problem is clicking on any element only selects the first item (shown below) which makes me think the partial is being rendered incorrectly.

Looking through the rails guide about rendering collection I wasn't able to find the answer.

Why isn't the <%= f.label :complete, task.name %> line working as expected?

About to click on baz:

enter image description here

Clicking on baz expecting baz to get checked but instead foo gets checked (note: the actual checkbox works but not the text next to the checkbox):

enter image description here

Edit:

Note I'm on the commit before the author adds ajax:

git checkout 1bb43bd

After bundling and starting the server:

curl http://localhost:3000/tasks | pbcopy

Gives the following html:

<!DOCTYPE html>
<html>
  <head>
    <title>Ckl</title>
    <meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="xlNcxfUn9NoUFZGrmeRGaK9uNhz01F43vs0ATt9qb+XIk414hTj37YZxDo1mAm3VOT7otj/qMgB+FLVaNsn8Aw==" />

    <link rel="stylesheet" media="all" href="/assets/layout.self-cc3852a9caa9db7dd4f2a4f654027564a1cb5bd14f24754194e6fd3129377e24.css?body=1" data-turbolinks-track="reload" />
<link rel="stylesheet" media="all" href="/assets/tasks.self-d679d83f2b24213289ec1a5948d0d54ec9798f954c5a996908ed19a7a108c6bf.css?body=1" data-turbolinks-track="reload" />
<link rel="stylesheet" media="all" href="/assets/application.self-af04b226fd7202dfc532ce7aedb95a0128277937e90d3b3a3d35e1cce9e16886.css?body=1" data-turbolinks-track="reload" />
    <script src="/assets/jquery.self-660adc51e0224b731d29f575a6f1ec167ba08ad06ed5deca4f1e8654c135bf4c.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/jquery_ujs.self-e87806d0cf4489aeb1bb7288016024e8de67fd18db693fe026fe3907581e53cd.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/turbolinks.self-c5acd7a204f5f25ce7a1d8a0e4d92e28d34c9e2df2c7371cd7af88e147e4ad82.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/action_cable.self-1641ec3e8ea24ed63601e86efcca7f9266e09f390e82199d56aa7e4bd50e1aa9.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/cable.self-6e0514260c1aa76eaf252412ce74e63f68819fd19bf740595f592c5ba4c36537.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/tasks.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/application.self-b89234cf2659d7fedea75bca0b8d231ad7dfc2f3f57fcbaf5f44ed9dc384137b.js?body=1" data-turbolinks-track="reload"></script>
  </head>

  <body>
    <div id="container">
      <h1>Task Dog</h1>

<a id="new_link" href="/tasks/new">New Task</a>

<h2>Incomplete Tasks</h2>
<div class="tasks" id="incomplete_tasks">
  <form class="edit_task" id="edit_task_4" action="/tasks/4" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="+1mGLeoE51+7p+uDVQmI2QCxwvbmuNRw4lnMEJbB25vekwOBavFs/Efo4X3AD5FMTE2EwJym4o462aUQjzda2w==" />
  <input name="task[complete]" type="hidden" value="0" /><input type="checkbox" value="1" name="task[complete]" id="task_complete" />
  <input type="submit" name="commit" value="Update" data-disable-with="Update" />
  <label for="task_complete">foo</label>
  <a data-confirm="Are you sure?" rel="nofollow" data-method="delete" href="/tasks/4">(remove)</a>
</form>
<form class="edit_task" id="edit_task_5" action="/tasks/5" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="dnc364MuSvkRuVLLRBnEG6cfoABSeoui7Iq729wmWQRgAxizDoT2oetX5WDSoITSQIs6Bi4GoGrkEqJicU6lhg==" />
  <input name="task[complete]" type="hidden" value="0" /><input type="checkbox" value="1" name="task[complete]" id="task_complete" />
  <input type="submit" name="commit" value="Update" data-disable-with="Update" />
  <label for="task_complete">bar</label>
  <a data-confirm="Are you sure?" rel="nofollow" data-method="delete" href="/tasks/5">(remove)</a>
</form>
<form class="edit_task" id="edit_task_6" action="/tasks/6" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="HW9YKsH9ETOugVJT0IkttgUwdjlUNL/MpXSjWagYJLG5fmjjZZWqInSEuQE2yhNmAOZkIFPeyd2leT3nia0g8g==" />
  <input name="task[complete]" type="hidden" value="0" /><input type="checkbox" value="1" name="task[complete]" id="task_complete" />
  <input type="submit" name="commit" value="Update" data-disable-with="Update" />
  <label for="task_complete">baz</label>
  <a data-confirm="Are you sure?" rel="nofollow" data-method="delete" href="/tasks/6">(remove)</a>
</form>

</div>

<h2>Comlpete Tasks</h2>
<div class="tasks" id="complete_tasks">

</div>

    </div>
  </body>
</html>

Upvotes: 0

Views: 130

Answers (1)

Taryn East
Taryn East

Reputation: 27747

Ok, so looking at the raw html I notice that every checkbox has the same html id:

id="task_complete"

That is where the issue stems from...

I don't know why your browser is reacting to that by checking only the first checkbox with that id, but it is a given requirement in html that id's must be unique across the entire html page (and that behaviour is not guaranteed if you don't).

So... now we know what the problem is... now you just need to figure out how to fix it. ;)

You can test this theory by manually passing in a unique id for each checkbox eg something like (note not bug-tested):

<%= f.check_box :complete, :id => "task_complete_#{task.id}" %>

Upvotes: 1

Related Questions