1

I am building a car share site and have a page for browsing existing journeys. At the top of the page is a search bar used to search for a location. I want to use Google Maps API to validate the place name and then send it to the controller with coordinates to then do a search within a radius.

For the life of me, no matter what combinations of code i use, i cannot seem to update the HiddenFor or search fields before the form is submitted to the controller. I know the code for validating places work as i use it on another page for creating journeys.

So the theory is the user enters a place name in the SearchString textbox, clicks the submit button, the jquery code then runs, validates the place, gets a correct location with geocoder, then updates the searchstring and coordinate hidden fields and finally posts to the controller.

Here is my current code:

@using (Html.BeginForm("BrowseJourney", "Journey", FormMethod.Post, new { id = "searchForm" }))
{    <div class="form-group" style="padding-bottom: 50px;">
        <div class="col-md-2">
            Find by location:
        </div>
        <div class="col-md-3">
            @Html.TextBox("SearchString", null, new { @class = "form-control" , id = "SearchString"})
        </div>
        <div class="col-md-2">
            Distance:
        </div>
        <div class="col-md-1">
            @Html.DropDownList("Distance", null, new { @class = "form-control" })
        </div>
        @Html.HiddenFor(model => model.SearchLatitude, new { id = "SearchLatitude" })
        @Html.HiddenFor(model => model.SearchLongitude, new { id = "SearchLongitude" })
        <div class="col-md-2">
            <input type="submit" value="Search" class="btn btn-default" id="submitButton" />
        </div>
    </div>   

}

And the javascript:

   <script src="https://maps.googleapis.com/maps/api/js?v=3&key=AIzaSyD4lap4yr45W9ztvRtfNw7JA-d03UVYtx0&region=GB" type="text/javascript"></script>
    <section class="scripts">
      <script type="text/javascript">

        $('#submitButton').click(function() {
          var address = document.getElementById("SearchString").value;
          var geocoder = new google.maps.Geocoder();
          geocoder.geocode({
            'address': address,
            componentRestrictions: {
              country: 'UK'
            }
          }, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
              document.getElementById("SearchString").value = results[0].formatted_address;
              document.getElementById("SearchLatitude").value = results[0].geometry.location.lat();
              document.getElementById("SearchLongitude").value = results[0].geometry.location.lng();
            } else {
              alert("Unable to find location");
              document.getElementById("SearchString").value = null;
            }
          });
        });
      </script>
    </section>

And finally the controller:

public ActionResult BrowseJourney(string searchString, int distance, string searchLatitude, string searchLongitude)
{
}

Any help is greatly appreciated!

Boggot
  • 79
  • 7
  • 1
    Side-note: if you are going to use jQuery at all, use it for your selectors. e.g. `document.getElementById("SearchString")` => `$("#SearchString")` etc :) It halves the size and is more readable (IMHO) – iCollect.it Ltd Jan 06 '16 at 15:24
  • Q: Where is your script placed in the file? It is not wrapped in a DOM ready handler so must follow the HTML it references. – iCollect.it Ltd Jan 06 '16 at 15:30
  • Sorry yes the script follows the HTML form inside @section scripts – Boggot Jan 06 '16 at 15:31
  • For starters, you should never use `click` handlers for forms as keyboard triggered submissions will not fire it. Use a `submit` handler. As you are using Visual Studio, place your script into a separate JS file, you can then simply breakpoint the code and see what is going on :) – iCollect.it Ltd Jan 06 '16 at 15:35
  • Updated answer below. I typed it from memory, and had the boolean value initially reversed. Should work now :) – iCollect.it Ltd Jan 06 '16 at 15:52

2 Answers2

1

The reason it does not work is you are adding code in a click handler, that then calls an asynchronous event and waits for the response.

In the meantime the form has already submitted.

You need to stop the form submitting and submit it from code when you have your values back.

Something like:

bool proceed = false;
$('#searchForm').submit(function(e) {
  if (!proceed) {
    var address = $("#SearchString").val();
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({
      'address': address,
      componentRestrictions: {
        country: 'UK'
      }
    }, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        $("#SearchString").val(results[0].formatted_address);
        $("#SearchLatitude").val(results[0].geometry.location.lat());
        $("#SearchLongitude").val(results[0].geometry.location.lng());
        proceed = true;  // Allow submit to proceed next time
        $('#searchForm').submit();
      } else {
        alert("Unable to find location");
        $("#SearchString").value = null;
      }
    });
  }
  return proceed;
});

Notes: Please use jQuery for all selectors. Much shorter and easier to follow (for jQuery coders). "In for a penny..."

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • 1
    Sir, you are a star. This worked flawlessly first time. I did have a .submit before but was trying something different with .click. I will now know for future to stick with .submit, and to also include the code to delay submitting till the values have been posted. – Boggot Jan 06 '16 at 16:02
0

I had the issue on mvc 5 and answer in below question helped me to resolve. Wait for form.submit() / POST to complete

can use e.preventDefault(); to prevent default submit.

Uday
  • 151
  • 1
  • 3
  • 15