提交表单之前异步获取坐标

时间:2018-09-11 14:55:49

标签: javascript jquery asynchronous post promise

我试图提交一个位置的输入字段,通过Google Geocoder查找纬度和经度,将其放在一些隐藏的字段中,然后以表单的形式发布。

有两个主要的阻止器,第一个是我的validateFields函数看不到添加到隐藏文本框中的值,第二个是延迟提交表单以将long和lat添加为表单的一部分。帖子。

我知道可以基于validateField检查使Submit事件返回true或false来延迟提交,但是即使使用Chrome Dev Tools,我也似乎看不到坐标。

$('#LocationSearchForm').submit(event => {
    let input = $('#SearchTerm').val();
    $('#Longitude'.val('23423'));
    $('#Latitude'.val('1111'));
    getLatLong().then(allowSubmit);
});

function getLatLong(input) {
    return new Promise(resolve => {
        let geocoder = new google.maps.Geocoder();
        geocoder.geocode({ address: input }, (results, status) => {
            if (status == google.maps.GeocoderStatus.OK) {
                $('#Latitude').val(results[0].geometry.location.lat());
                $('#Longitude').val(results[0].geometry.location.lng());
            }
        });
        resolve(console.log(`applied coordinates to hidden fields`));
    });
}

function validateFields() {
    if ($('#Latitude').val() === '' && $('#Longitude').val() === '') {
        return false;
    }
    return true;
}

function allowSubmit() {
    return validateFields();
}

HTML

<form id="LocationSearchForm" action="POST">
    <input id="SearchTerm" type="text" placeholder="Find a city" value>
    <input id="Latitude" type="hidden" value>
    <input id="Longitude" type="hidden" value>
</form>

2 个答案:

答案 0 :(得分:0)

首先,您需要在resolve()回调内移动geocode。目前,它正在立即解决,但是geocode()是异步的。

geocoder.geocode({ address: input}, (results, status) => {
  if (status == google.maps.GeocoderStatus.OK) {
    $('#Latitude').val(results[0].geometry.location.lat());
    $('#Longitude').val(results[0].geometry.location.lng());
    // resolve now that data updated
    resolve(console.log(`applied coordinates to hidden fields`));
  } else {
    // reject here
  }
});

submit回调中,您需要阻止立即提交,以便有时间进行异步操作。一旦诺言解决,您就可以使用本机提交

$('#LocationSearchForm').submit(function(event){
    event.preventDefault()
    let form = this;

    getLatLong().then(function(){
      if(validateFields()){
         // use native submit to by-pass jQuery listener
         form.submit()
      }else{
          // alert user of problems
      }
    }).catch(function(err){ /*do something for geocode rejection */});
});

答案 1 :(得分:0)

非常感谢你们。作为参考,我在@charlietfl的答案的帮助下以这种方式工作。

$('#LocationSearchForm').submit(event => {
    event.preventDefault();
    let input = $('#SearchTerm').val();

    getLatLong(input)
        .then(() => {
            return !validateFields() ? $('form')[0].submit() : null;
        })
        .catch(err => {
            console.log(err);
        });
});

function getLatLong(input) {
    return new Promise((resolve, reject) => {
        let geocoder = new google.maps.Geocoder();
        geocoder.geocode({ address: input }, (results, status) => {
            if (status == google.maps.GeocoderStatus.OK) {
                $('#Latitude').val(results[0].geometry.location.lat());
                $('#Longitude').val(results[0].geometry.location.lng());
                resolve(true);
            } else {
                reject(false);
            }
        });
    });
}

function validateFields() {
    return $('#Latitude').val() === '' && $('#Longitude').val() === '';
}

使用'this'对我不起作用,但是也许因为我坚持使用箭头功能,当与jQuery混合使用时,这是不好的做法吗?我尝试了$('#LocationSearchForm'),但没有用,所以我不得不改用$('form')[0].submit(),但是我不确定提交这样的表单是否是一种好习惯。

感谢@Bergi在提交建议时返回布尔值,与使用显式submit()preventDefault相比,这似乎是延迟提交的一种不错的选择