Выполните и завершите геокодирование карт Google, прежде чем разрешить отправку для продолжения.

У меня есть представление магистрали с некоторой проверкой формы. Проверка формы использует preventDefault, если в форме есть ошибки. Если это не так, он должен принять значение в поле ввода, получить lat, lng и заполнить два скрытых поля, прежде чем продолжить отправку. Я пытаюсь использовать отложенный, но не уверен, что я ошибся. Я вырезал некоторые ненужные фрагменты здесь и там, чтобы было чище размещать здесь.

Я пробовал использовать preventDefault с отложенным (которое мне все равно не нужно было исправлять?), но повторная отправка с использованием события отправки представляет собой некоторую проблему.

Без preventdefault поля lat, lng не обновляются перед отправкой. Возможно, неправильная реализация deferred/promise или при использовании preventdefault отправка снова запускает проверку, и я попадаю в цикл. Я не хочу использовать setTimeout, потому что не хочу задерживать пользователя дольше, чем получить ответ.

events: {
  'submit': 'validateForm'
},
validateForm: function(e){

//lotsa validation then

  var loc = $('#location').length;
  if ( loc ){  
    var parent = $(e.currentTarget).closest('form');
    e.preventDefault();
    $.when(this.getCoordinates(e))
    .done(function(){
      parent.submit();
    });
  }
},

getCoordinates : function(e) {
    var deferred = $.Deferred();
    var that = this;
    var parent = $(e.currentTarget).closest('form');
    var addr =  parent.find('#location').val();

    if ($.trim(addr).length) {
        var apiurl = '//maps.googleapis.com/maps/api/geocode/json?address=' + addr '&bounds=' + bounds + '';
        $.ajax({
            url : apiurl,
            dataType : 'json'
        })
        .done(function (data) {

            try {
                if(!data.results.length){
                    return;
                }
                var coord = data.results[0].geometry.location;
                var result = data.results[0].formatted_address;
                if (coord) {
                    var lat = coord.lat;
                    var lon = coord.lng;

                    parent.find("input[data-geo-type = 'lat']").val(lat);
                    parent.find("input[data-geo-type = 'lng']").val(lon);
                    deferred.resolve();
                }

            } catch (e) {
                console.error(e);
            }
        }).fail(function () {
             $(e.currentTarget).val(addr);
        });
    } else {
       deferred.reject(); 
    }
return deferred.promise();
}, 

Любая помощь или указатели приветствуются!


person Mr Brimm    schedule 08.04.2016    source источник
comment
Ваша проблема в том, что validateForm не запускает отправку формы? или что-то другое? Что здесь делает submitCoordinates?   -  person T J    schedule 08.04.2016
comment
submitCoordinates() или getCoordinates()? Также фигурные скобки не сбалансированы. Исправьте вопрос, может кто ответит.   -  person Roamer-1888    schedule 08.04.2016
comment
Я исправил имя метода и скобку. Без preventdefault поля lat, lng не обновляются перед отправкой. Возможно, неправильная реализация deferred/promise или при использовании preventdefault отправка снова запускает проверку, и я попадаю в цикл. Я не хочу использовать setTimeout, потому что не хочу задерживать пользователя дольше, чем получить ответ. Спасибо,   -  person Mr Brimm    schedule 08.04.2016
comment
Вы не разрешаете/отклоняете, если $.trim(addr).length ложно.   -  person Kevin B    schedule 08.04.2016
comment
кроме того, parent.submit() повторно инициирует событие отправки, что может привести к бесконечному циклу. Вы испытываете бесконечный цикл? (вы увидите, что он постоянно получает координаты от Google на вкладке вашей сети)   -  person Kevin B    schedule 08.04.2016
comment
Нет, form.submit() намеренно не запускает событие отправки формы именно по этой причине. Так было с самых первых дней HTML/javascript.   -  person Roamer-1888    schedule 08.04.2016
comment
@MrBrimm, код немного сбивает с толку. e.currentTarget было бы адресным полем только в том случае, если бы validateForm() вызывалось особым образом.   -  person Roamer-1888    schedule 08.04.2016
comment
@Roamer-1888 Roamer-1888 Я изменил переменную адреса, но геокодирование не завершается до отправки с удаленным preventDeafault, и я попаду в цикл, если оставлю его включенным. Спасибо   -  person Mr Brimm    schedule 08.04.2016
comment
@KevinB, ты прав насчет цикла. Не знаю, как решить эту проблему. Я добавил отказ, но до сих пор не понимаю, почему он не работает, даже если addr.length имеет значение true. Спасибо.   -  person Mr Brimm    schedule 08.04.2016
comment
Если это зацикливание, то решение простое: замените .submit() на [0].submit(). это позволит вам обойти любые связанные события и вместо этого просто выполнить действие.   -  person Kevin B    schedule 08.04.2016
comment
@ Roamer-1888 Roamer-1888 Это правда, если только вы не вызываете .submit() для объекта jquery, как здесь. Вместо этого jQuery вызовет событие, и только после того, как все события будут запущены, он отправит его и только в том случае, если ни одно из событий не вернуло false или не предотвратило значение по умолчанию.   -  person Kevin B    schedule 08.04.2016
comment
@KevinB сделал свое дело. Я пробовал это раньше, но вы заставили меня пересмотреть это, и я понял, что получаю отправку, это не функция, потому что чертова кнопка отправки имеет id=submit. Я изменил идентификатор, и теперь он работает. Спасибо!   -  person Mr Brimm    schedule 09.04.2016
comment
хахаха, да, это тоже распространенная ошибка.   -  person Kevin B    schedule 09.04.2016


Ответы (1)


Похоже, вы, вероятно, сталкиваетесь с бесконечным циклом из-за вашего внутреннего parent.submit(). Поскольку parent является объектом jQuery, он повторно запускает все события, что приводит к бесконечному повторению ajax. К счастью, решение простое. Вместо вызова .submit() для объекта jQuery вызовите его для самой формы. Вы также должны убедиться, что у вас нигде нет id="submit". Вызывая его непосредственно в форме, вы просто отправляете форму, не вызывая никаких событий.

validateForm: function(e){

//lotsa validation then

  var loc = $('#location').length;
  if ( loc ){  
    var parent = $(e.currentTarget).closest('form');
    e.preventDefault();
    $.when(this.getCoordinates(e))
    .done(function(){
      //parent.submit();
      parent[0].submit();/* modified line */
    });
  }
},
person Kevin B    schedule 08.04.2016