0

I tried to use the callback function but it still has no effect. Here is the HTML:

<form action="{% url 'seller_details' %}" method="post" id="seller_details">
    {% csrf_token %}
    <div>
        <div class="heading">PERSONAL INFORMATION</div>
        <table>
            <tr>
                <td id="wd25">Full Name</td>
                <td><input type="text" placeholder="Full Name" name="full_name" value="{{full_name}}"/></td>
            </tr>
            <tr>
                <td>Mobile Number</td>
                <td><input type="text" placeholder="Mobile Number" value="{{mobile}}" name="mobile"/></td>
            </tr>
            <tr>
                <td>Store Address</td>
                <td><textarea rows="5" placeholder="Store Address" name="pickup_address" value="{{pickup_address}}"></textarea></td>
            </tr>
        </table>
</form>

Then I tried to validate the form and submit the form using submit handler of jQuery validate

$("#seller_details").validate({
    rules: {
        full_name: "required",
        pickup_address:"required",
    },
    messages: {
        full_name: "Please enter Name",
        mobile: "Please enter Mobile Number",
       pickup_address:"Please enter address",
    },
    submitHandler: function(form){
        var form = $(form).serialize()

        codeLatLng(storeGeoAddress);

        console.log(latitude)
        console.log(longitude)

        $.ajax({        
            type: "post",
            url: "{% url 'seller_details' %}",     
            data: form + "&csrfmiddlewaretoken=" + '{{csrf_token}}' + '&latitude=' + latitude + '&longitude=' + longitude,

I used the following asynchronous function called geocoder to get the latitude and longitude of the address submitted

function codeLatLng(callback) {
    var address = $("textarea[name=pickup_address]").val();
    if (geocoder) {
        geocoder.geocode({'address': address}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                if (results[0]) {
                    callback(results[0]);
                } else {
                    alert("No results found");
                }
            } 
            else {
                alert("Geocoder failed due to: " + status);
            }
        });
    }
}

function storeGeoAddress(addr) {     
    latitude = addr.geometry.location.lat();
    longitude = addr.geometry.location.lng();
}

The problem I am facing here is that I am not able to gather the values of latitude and longitude so that I can give it back to my submit handler so that it can post the values? What can I do in such a scenario? Thank you

Latitude and Longitude are globally defined here

console.log(latitude) console.log(longitude) are not able to log anything

Is there any Way by Which i can make Submit Handler as my callback function?

5
  • What is the scope of your latitude and longitude variables? If they're within scope of both functions then what you have should work, although it's rather odd placing a JSON string in the querystring of a request. You would be best just sending a plain object and letting jQuery encode it for you. Commented Mar 7, 2016 at 9:14
  • What you have will not work regardless of the scope of latitude and longitude. $.ajax will run before the storeGeoAddress callback gets fired because the logic in storeGeoAddress is async. You need to perform your AJAX in your callback. Then you can also sack of the nasty global variables. Commented Mar 7, 2016 at 9:15
  • both variables are global Commented Mar 7, 2016 at 9:23
  • then in that case the submit handler should be the callback Commented Mar 7, 2016 at 9:55
  • Any Chance that i can make submit handler as callback? Commented Mar 7, 2016 at 10:14

3 Answers 3

2

Promises to the rescue.

jQuery has a Promise implementation that is useful enough for your situation. How about this.

First, write a geocode-Helper that wraps Google's callback-based API method and returns the promise of a resolved address instead:

function geocodeAsync(addrString) {
    var result = $.Deferred();

    if ( !(geocoder && geocoder.geocode) ) {
        result.reject("geocoder not defined");
    } else {
        geocoder.geocode({address: addrString}, function (results, status) {
            if (status === google.maps.GeocoderStatus.OK) {
                if (results.length) {
                    result.resolve(results[0]);
                } else {
                    result.reject("No results found");
                }
            }
            else {
                result.reject("Geocoder failed due to: " + status);
            }
        });
    }

    return result.promise();
}

Now, things get easy. You can use that function in exactly the same way you would use jQuery's Ajax functions:

$("#seller_details").validate({
    rules: {/* ... */},
    messages: {/* ... */},
    submitHandler: function (form) {
        var address = $(form).find("textarea[name=pickup_address]").val();

        geocodeAsync(address).done(function (geocodeResult) {
            var otherParams = {
                'parameter[]': JSON.stringify(parameter),
                csrfmiddlewaretoken: '{{csrf_token}}',
                latitude: geocodeResult.geometry.location.lat(),
                longitude: geocodeResult.geometry.location.lng()
            },
            postBody = [ $(form).serialize(), $.param(otherParams) ].join('&');

            $.post("{% url 'seller_details' %}", postBody).done(function (result) {
                // whatever you want to do on POST success
            }).fail(function (jqXhr, status, error) {
                // seller_details update failed
            });
        }).fail(function (reason) {
            alert("Geocoding failed because: " + reason);
        });
    }
});

No global variables needed and when reading the code you see exactly what happens.

Relevant documentation: https://api.jquery.com/jQuery.Deferred/

Sign up to request clarification or add additional context in comments.

6 Comments

what is results in else part? i think it should be result.reject ?
@AdrafeRinzzler Right, that was a typo. I should have thought of better variable names than result and results.
var address = $(form).find("textarea[name=pickup_address]").val();
postBody = [ $(form).serialize(), $.param(otherParams) ].join('&'); says unrecognized exp ...why so?
$(form).find() is not the same as form.find(). I also can't see a syntax error there. [ $(form).serialize(), $.param(otherParams) ].join('&') is equally valid. Are you using the code as I posted it or have you made changes?
|
2

You're in callback hell! This is a fairly common problem to have in javascript. The way you return "synchronously" from an asynchronous call is through a Promise. Either that or you have to pass along a chain of callbacks to handle the various steps that must occur.

My favorite JS Promise implementation is https://github.com/cujojs/when, and I recommend you follow this guide: http://blog.briancavalier.com/async-programming-part-1-it-s-messy/

2 Comments

what about jquery solutions?
Any Chance that i can make submit handler as callback?
1

You can still create the callback inside the submitHandler

codeLatLng(function(addr){
    var latitude = addr.geometry.location.lat();
    var longitude = addr.geometry.location.lng();

    console.log(latitude)
    console.log(longitude)

    $.ajax(...);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.