José Cisneros
José Cisneros

Reputation: 3

Ruby on Rails/HTML table

This is the edited code: I tried with 'name' instead of 'latitude', and I still get a blank alert window. I also added <script src="//code.jquery.com/jquery-2.1.1.min.js"></script> inside the <head> in app/views/layouts/application.html.erb

    <% @clients.each do |client| %>
          <tr class = "client">
            <td class = "name"><%= client.name %></td>
            <td class = "phone"><%= client.phone %></td>
            <td class = "address"><%= client.address %></td>
            <td class = "pay"><%= client.pay %></td>
            <td class = "latitude"><%= client.latitude %></td>
            <td class = "longitude"><%= client.longitude %></td>
            <td><form><input class = "route" type="checkbox" name = "chkboxRoute"></form></td>
          </tr>
        <% end %>

<script>
$(function() {
  $(".client input.route").bind("change", function(element) {
    var clatitude = [];
    var clongitude = [];

    $(".client input.route:checked").each(function(element) {
      element = $(element);

      var clientLatitude = $(element).closest('.client').find('.latitude');
      clatitude.push(clientLatitude.text());

      var clientLongitude = $(element).closest('.client').find('.longitude');
      clongitude.push(clientLongitude.text());
    });
        window.alert(clatitude[0]);
  })
});
</script>

Upvotes: 0

Views: 1049

Answers (2)

Michael Chaney
Michael Chaney

Reputation: 3031

Add some data - your client.id if nothing else, to the checkbox in some way. It'll make your life easier. You can do that in a couple of ways, but the easiest is as part of the name:

<input type="checkbox" name = "chkboxRoute_<%= client.id %>">

or

<input type="checkbox" name = "chkboxRoute[]" value="<%= client.id %>">

With HTML5 you can use a separate "data-client-id" attribute or something like that.

Do you want to access the data from javascript or back in Rails? If you want the name or something else just stick it in the value or other attribute of the checkbox.

The "" stuff is extraneous, particularly if you want to just access this via javascript.

Revision based on comment below:

I would modify the html as such:

<% @clients.each do |client| %>
  <tr class="client">
    <td class="client_<%= client.id %> name"><%= client.name %></td>
    <td class="client_<%= client.id %>phone"><%= client.phone %></td>
    <td class="client_<%= client.id %>address"><%= client.address %></td>
    <td class="client_<%= client.id %>pay"><%= client.pay %></td>
    <td class="client_<%= client.id %>latitude"><%= client.latitude %></td>
    <td class="client_<%= client.id %>longitude"><%= client.longitude %></td>
    <td><input class="route" type="checkbox" name = "chkboxRoute" value="client_<%= client.id %>"></td>
  </tr>
<% end %>

That makes your html a little more complex but the javascript is then simplified. Again, Chris code is solid so I won't replicate everything he's done. With the html changed thusly you can directly grab the values that you want:

$(".client input.route:checked").each(function(element) {
  var client_class = $(element).val();
  var client_name = $("." + client_class + " name").text();
  var client_phone = $("." + client_class + " phone").text();
  ...
});

I just like doing something like that because it doesn't rely so much on the structure of the html.

Now, if you want to really go for the gold here's the way I would do it:

<% @clients.each do |client| %>
  <tr class="client">
    <td><%= client.name %></td>
    <td><%= client.phone %></td>
    <td><%= client.address %></td>
    <td><%= client.pay %></td>
    <td><%= client.latitude %></td>
    <td><%= client.longitude %></td>
    <td><input class="route" type="checkbox" name = "chkboxRoute" value="<%= client.id %>"></td>
  </tr>
<% end %>

<script type="text/javascript">
  var clients = [];
  <% @clients.each do |client| %>
    clients[<%= client.id %>] = {
      name: "<%= j(client.name) %>",
      phone: "<%= j(client.phone) %>",
      ....
    };
  <% end %>
</script>

Then, getting the values is simply a matter of this:

$(".client input.route:checked").each(function() {
  var client_id = parseInt($(this).val());
  var client_name = clients[client_id].name;
  var client_phone = clients[client_id].phone;
  ...
});

You can even use a json template to put the array together if you like. Anyway, that should give you plenty to chew on.

Upvotes: 1

Chris
Chris

Reputation: 12181

You should include the JQuery library to help you out. In your layout.html.erb file, add this inside the <head>:

<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>

JQuery has the eq function to select based on index docs.

There is also the siblings function that will return the nodes nested within the same parent element (in this case <tr>. You can also include a selector to further pare down results.

Example excerpt from app/views/clients/index.erb:

<% @clients.each do |client| %>
  <tr class="client">
    <td class="name"><%= client.name %></td>
    <td class="phone"><%= client.phone %></td>
    <td class="address"><%= client.address %></td>
    <td class="pay"><%= client.pay %></td>
    <td class="latitude"><%= client.latitude %></td>
    <td class="longitude"><%= client.longitude %></td>
    <td><form><input class="route" type="checkbox" name = "chkboxRoute"></form></td>
  </tr>
<% end %>

And the Javascript:

// $ is the jQuery global object
// Passing it a function will wait to execute that code until
// the entire HTML document is ready
$(function() {
  // Select every input with the "route" class that is checked
  var names = [];
  $(".client input.route:checked").each(function(index, element) {
    // Wrap the element in jQuery so we get access to all of its functions
    element = $(element);

    // Find the closest element with class "client",
    // then find an element nested inside of it with class "name"
    var clientName = $(element).closest('.client').find('.name');

    // Add the text from that element to the array
    names.push(clientName.text());
  });

  // At this point, names will hold all of the names of the clients
  // with a checked route input
});

Note that this will only run at the time the page loads. If you want it to run any time one of those changes, you can bind the function to the change event:

$(function() {
  $(".client input.route:checked").bind("change", function(element) {
    var names = [];
    $(".client input.route:checked").each(function(element) {
      element = $(element);
      var clientName = $(element).closest('.client').find('.name');
      names.push(clientName.text());
    });
  })
});

This will run through all of them every time a checkbox is changed. Not the best for performance, but that should get you started.

Upvotes: 2

Related Questions