简体   繁体   English

用ENTER提交表单与单击提交按钮时的行为不同

[英]Different behavior when form is submitted with ENTER vs. clicking submit button

I have an HTML form input element that uses a SearchBox from the Google Maps Places API for auto-completion. 我有一个HTML表单输入元素,该元素使用Google Maps Places API中的SearchBox来自动完成。 In my JavaScript I have created a SearchBox instance as follows: 在我的JavaScript中,我创建了一个SearchBox实例,如下所示:

var input = $('#spotsearch')[0];  // Refers to a form input with type="text" in my HTML
searchBox = new google.maps.places.SearchBox(input);

Later in in my JavaScript, I have the following: 稍后在我的JavaScript中,我具有以下内容:

$('#searchform').submit(function () {
    var places = searchBox.getPlaces();
    if (places) {
        var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
        var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
        $('#latitude').val(spotLat);
        $('#longitude').val(spotLng);
    }

});

Here is my issue: after selecting a completion candidate, when I submit the form by clicking the form's submit button, everything works as expected, and places will reference an array with a single object. 这是我的问题:选择完成候选人后,当我通过单击表单的“提交”按钮提交表单时,一切都按预期进行,并且places将引用具有单个对象的数组。 However, if I submit the form by pressing ENTER , the anonymous function still gets called, but places returns an empty array. 但是,如果我通过按ENTER提交表单,则仍会调用匿名函数,但Places返回一个空数组。 In both cases, it seems that the request being sent is exactly the same. 在这两种情况下,似乎发送的请求是完全相同的。 What am I missing here? 我在这里想念什么?

I am new to JavaScript and to the Goggle Maps API, so I am not sure where my mistake originates. 我是JavaScript和Goggle Maps API的新手,所以我不确定我的错误源于何处。 My intuition is that it may be related to timing in some way, but that is really just a vague hunch. 我的直觉是,它可能以某种方式与计时相关,但这实际上只是模糊的预感。 Any suggestions would be appreciated. 任何建议,将不胜感激。 Thank you! 谢谢!

Edit: 编辑:

To provide a bit more detail, here is my entire script: 为了提供更多细节,这是我的整个脚本:

var searchBox;
var places;
function initSearchBox() {
    var KCLatLng = new google.maps.LatLng({lat: 39.093201, lng: -94.573419});
    var bounds = new google.maps.LatLngBounds(KCLatLng);

    var input = $('#spotsearch')[0];
    searchBox = new google.maps.places.SearchBox(input);
    searchBox.setBounds(bounds);

    $('#searchform').submit(function () {
        var places = searchBox.getPlaces();
        if (places) {
            var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
            var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
            $('#latitude').val(spotLat);
            $('#longitude').val(spotLng);
        }

    });
}

initSearchBox is then passed as the callback parameter when I load the Goggle Maps API. 然后,当我加载initSearchBox Maps API时, initSearchBox作为callback参数传递。

I have also tried doing it this way: 我也尝试过这种方式:

var searchBox;
var places;
function initSearchBox() {
    var KCLatLng = new google.maps.LatLng({lat: 39.093201, lng: -94.573419});
    var bounds = new google.maps.LatLngBounds(KCLatLng);

    var input = $('#spotsearch')[0];
    searchBox = new google.maps.places.SearchBox(input);
    searchBox.setBounds(bounds);
    searchBox.addListener('places_changed', function() {
        var places = searchBox.getPlaces();
        if (places) {
            var spotLat = searchBox.getPlaces()[0].geometry.location.lat();
            var spotLng = searchBox.getPlaces()[0].geometry.location.lng();
            $('#latitude').val(spotLat);
            $('#longitude').val(spotLng);
        }
    });
}

But this gives me the same result (hitting ENTER does not set the value of #latitude or #longitude , but clicking the submit button does). 但这给了我相同的结果(按ENTER不会设置#latitude#longitude的值,但是单击#longitude按钮可以)。

Here is the HTML of my form (using Django templates and Bootstrap): 这是我的表单的HTML(使用Django模板和Bootstrap):

<form method="get" id="searchform" action="{% url 'spot_search' %}"
      class="navbar-form navbar-left plain" role="search">
    <div class="form-group">
        <input id="spotsearch" type="text" class="form-control plain"
               placeholder="Search spots" name="search_query">
    </div>

    <button type="submit" class="btn btn-default plain">
        <span class="glyphicon glyphicon-search"></span> Search
    </button>
    <input id="latitude" name="latitude" type="hidden">
    <input id="longitude" name="longitude" type="hidden">
</form>

Is this getting submitted to a server? 这是提交给服务器吗? If so, it's probably a race condition. 如果是这样,那可能是比赛条件。 The form isn't waiting for the hidden fields to get set before submitting to the server. 在提交给服务器之前,表单不等待隐藏字段的设置。 Regardless of whether you set the values from within the form submit event or the places_changed event of the SearchBox, you will still need to either prevent the enter key from submitting the form to the server or prevent the form from being submitted via user action so you can programmatically submit it later when your data is set. 无论您是从表单提交事件还是SearchBox的places_changed事件中设置值,您都仍然需要阻止Enter键将表单提交到服务器,或者阻止表单通过用户操作提交,因此您可以在设置数据后以编程方式提交。

To disable the enter key from submitting the form, look here: Google Autocomplete - enter to select 要禁用Enter键提交表单,请查看此处: Google自动填充-输入以选择

To disable the form submission, do as Juan suggested and include e.preventDefault(); 要禁用表单提交,请按照Juan的建议进行操作,并包含e.preventDefault();

I think that reason why the submit event handler is triggered when you press the enter button, but without places as an empty array is because the event handler is executed before than the initSearchBox function. 我认为之所以在按下Enter键时触发提交事件处理程序但没有放置空数组的原因是因为该事件处理程序是在initSearchBox函数之前执行的。 It is possible that you previosly executed the initSearchBox so you had attached the submit event handler. 您有可能事先执行了initSearchBox,因此已附加了Submit事件处理程序。

My recommendations is to replace your code by this one: 我的建议是用以下代码替换您的代码:

 $('#searchform').submit(function (e) { var KCLatLng = new google.maps.LatLng({lat: 39.093201, lng: -94.573419}); var bounds = new google.maps.LatLngBounds(KCLatLng); var input = $('#spotsearch')[0]; var searchBox = new google.maps.places.SearchBox(input); searchBox.setBounds(bounds); var places = searchBox.getPlaces(); if (places) { var spotLat = searchBox.getPlaces()[0].geometry.location.lat(); var spotLng = searchBox.getPlaces()[0].geometry.location.lng(); $('#latitude').val(spotLat); $('#longitude').val(spotLng); } // Prevent to perform a "real" submit (so page is not reloaded or redirected) e.preventDefault(); }); 

In this way all the entire search code is going to be executed when the form is submitted. 这样,提交表单时,将执行所有完整的搜索代码。

Thanks @adam0101 for pointing me to this question . 感谢@ adam0101为我指出这个问题 I also found the related questions here , here and here to be useful. 我还在这里这里这里找到了相关的问题。 I missed them in my first pass at researching the issue, because the issue was more specific to the Google Maps autocomplete API than I had realized. 我在研究此问题的第一阶段就错过了他们,因为该问题比我所意识到的更具体地针对Google Maps自动完成API。

While I considered marking my question as duplicate, I have decided to instead post the solution that I ended up going with, which is heavily inspired by this highly upvoted - but not accepted - answer. 虽然我认为我的标记为重复的问题,我已决定,而不是张贴我结束了,这在很大程度上受到鼓舞去解决这个高度upvoted -但不接受-答案。 I simply added the following to my existing JavaScript: 我只是将以下内容添加到现有的JavaScript中:

$('#spotsearch').keydown(function (e) {
    // Don't submit form unless values have been set
    var condition = $('#latitude').val() == "" && $('#longitude').val() == "";
    if (e.which == 13 && condition) {
        return false;
    }
});

This way, the first time the user presses enter on an autocompletion candidate it will select that candidate (instead of submitting the form before the candidate can be selected). 这样,用户第一次按下Enter时会选择该自动完成候选(而不是在可以选择该候选之前提交表单)。 Then the user can either hit enter again to submit the form, or click the Search button to do the same thing. 然后,用户可以再次按Enter键以提交表单,或者单击“ Search按钮执行相同的操作。 The solution it is modeled after is this one: 它所建模的解决方案是以下一种:

$('#inputId').keydown(function (e) {
  if (e.which == 13 && $('.pac-container:visible').length) return false;
});

from the answer linked above. 从上面链接的答案。 I modified this slightly so that it does not depend on the SearchBox having a particular class defined by Google and out of my control. 我对此做了一些修改,以使其不依赖于SearchBox具有Google定义的特定类并且不受我的控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 单击“ Enter”按钮时提交表单,并进行验证 - Submit form when Clicking “Enter” button, with validation 当里面没有提交按钮时,表单不会在回车键上提交 - form is not submitted on enter key when there is no submit button inside 单击输入时将提交按钮设置为另一个 - Set submit button to another when clicking enter 单击时禁用提交按钮将阻止在Google Chrome上提交表单 - Disabling a submit button when clicking on it , will prevent the form from being submitted on Google Chrome 为什么单击未标记为提交的按钮会导致提交表单? - Why does clicking on a button that's not marked as submit cause a form to be submitted? 单击提交按钮后,将表单提交的文本值分配给变量 - allocate text value submitted by a form to a variable after clicking submit button 单击输入并按下提交按钮提交表单数据 - Submit form data both on clicking enter and hitting the submit button 当按Enter提交表单时,按钮onclick可以正常工作,但有不良行为 - Button onclick works fine but undesired behavior when pressing enter to submit form XMLHttpRequest对<input type =“button”>与<button>的不同行为 - Different Behavior of XMLHttpRequest for <input type=“button”> vs. <button> 按回车键提交表格,不按按钮 - Submit form when press enter, not press button
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM