Hours of struggle, problem lies in HTML

Apr 27, 2018

Multiple hours wasted over the past two days because of HTML semantic violations.. I’m implementing booking, the available times as well as the booked times, and everything works great, so I want to book and cancel bookings through AJAX.

Posts index

First problem occurred when I wanted to implement the “book” button. When I clicked the button nothing happened, but after I refreshed the page and clicked on the button again, it would work as intended and book the time. I couldn’t understand why it worked half the time, so after multiple hours of searching the web, I looked at the Rails generated HTML code (properly should have done that sooner).

The Rails code:

  
  <%= simple_form_for Booking.new do |f| %>
    <%= f.hidden_field :date, value: booking_date(params[:date], time) %>
    <%= f.hidden_field :washer_id, value: @washers[i].id %>
    <td><%= f.button :submit, "Book", class: 'btn btn-light' %></td>
  <% end %>
  
  

And what it generated in HTML:

  
  <form novalidate="novalidate" class="simple_form new_booking" id="new_booking" action="/bookings" accept-charset="UTF-8" data-remote="true" method="post"></form>
  <input name="utf8" type="hidden" value="✓">
  <input value="2018-05-06T06:30:00+00:00" type="hidden" name="booking[date]" id="booking_date">
  <input value="1" type="hidden" name="booking[washer_id]" id="booking_washer_id">
  <td>
    <input type="submit" name="commit" value="Book" class="btn btn-default btn btn-light" data-disable-with="Book">
  </td>
  
  

Clearly something was wrong; the form tag closed without the inputs. The problem was the HTML semantics; I was breaking the form with the td tag.

So I fixed my code:

  
  <td>
    <%= simple_form_for Booking.new do |f| %>
      <%= f.hidden_field :date, value: booking_date(params[:date], time) %>
      <%= f.hidden_field :washer_id, value: @washers[i].id %>
      <%= f.button :submit, "Book", class: 'btn btn-light' %>
    <% end %>
  </td>
  
  

And the HTML now looks like this:

  
  <td>
    <form novalidate="novalidate" class="simple_form new_booking" id="new_booking" action="/bookings" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓">
      <input value="2018-05-06T11:00:00+00:00" type="hidden" name="booking[date]" id="booking_date">
      <input value="1" type="hidden" name="booking[washer_id]" id="booking_washer_id">
      <input type="submit" name="commit" value="Book" class="btn btn-default btn btn-light" data-disable-with="Book">
    </form>
  </td>
  
  

The form with all the inputs INSIDE the table cell as plan in the first place.

The reason why it took so long for me to figure out was that it worked half the time. When you would enter the page and clicked the button, nothing would happen, but if you refreshed the page and clicked again, it would work as intended.

A new problem occurred when I was implementing the “cancel booking” function.

The Rails code was a follows:

  
  <%= links_to 'Cancel booking', booking_path(booking),
                                              class: 'btn btn-light',
                                              method: :delete,
                                              remote: true %>
  
  

Yet again I had a scenario when it worked and another where it didn’t. Turns out you can’t make a request to the same url with delete and get with AJAX through a link. So when I removed remote: true it worked like a charm, but I don’t want the page to refresh every time.

So the solution was to make it a button instead of a link, like so:

  
  <%= button_to 'Cancel booking', booking_path(booking),
                                              class: 'btn btn-light',
                                              method: :delete,
                                              remote: true %>
  
  

Then everyone can live happily ever after.

This concludes another post, and I’m finally getting some of the key functionality down, actually the most important functionality, the idea that started the whole thing. Feels good.

No comments yet.

Add comment