Why doesn't this AJAX script work?

Former Member
Former Member

I was wondering if all the relevant JQuery libraries are included by default, as I am having trouble trying to get this AJAX code to post. It doesn't do anything.

	$(document).ready(function() {
    $("select.country").change(function(){
        var selectedCountry = $(".country option:selected").val();
        $.ajax({
            type: "POST",
            url: "$core_v2_page.Url",
            data: { country : selectedCountry } 
        }).done(function(data){
            $("#response").html(data);
        });
    });
});

And the velocity code:

#set($countries = false)
#set($countries = $Ibby_v1_LocationData.GetAllCountries())
<form>
<div>
#if ($countries)
 <label>Country:</label>
                <select class="country">
                    <option>Select</option>
                    #foreach ($country in $countries)
                        <option value="$country.iso2">$country.country</option>
                    #end
                </select>
#else

#end
</div>
<div>   

#if ($core_v2_page.IsPost)
$core_v2_page.SetContentType('application/json')

#set($country = false)
#set($country = $core_v2_page.GetFormValue('country'))
#if ($country)
#set($regions = $Ibby_v1_LocationData.GetRegionsInCountry($country))

	    #if($country != 'Select')
        <label>Region:</label
        <select>
        #foreach($region in $regions)
            <option>$region</option>
        #end
        </select>
        #end
#end
#end

</div>
</form>
<div id="response"></div>
</div>



Edited
[edited by: IbrahimK at 12:01 PM (GMT 0) on Wed, Jul 22 2020]
Parents
  • How are you rendering the javascript code? You have Velocity and jQuery but I don't see it in the Velocity code. You could pass the $core_v2_page.Url value as a parameter from the widget's Velocity script to the Javascript if it is a separate file. 

    Have you verified that the HTML and script are rendered correctly and without javascript errors?

    A few notes:

    • When rendering elements that your widget will interact with, it is best to scope your selectors either to the wrapping element ID ($core_v2_widget.WrapperElementId which is the ID of the DIV tag wrapping the content of the widget) or generate a unique ID for each interactive element ($core_v2_widget.UniqueId('country')).
    • When implementing AJAX requests, it is recommended to use a separate Velocity or server-side Javascript file to handle the callback which will be more efficient that posting back the entire document and includes security validation when used with $.telligent.evolution.post/put/del. See https://community.telligent.com/community/11/w/developer-training/65122/using-ajax#Custom_Widget-Defined_AJAX_Endpoints 
    • jQuery will provide the selected value of a select  box with just $('SELECT_BOX_SELECTOR').val() -- no need to filter by selected option.
Reply
  • How are you rendering the javascript code? You have Velocity and jQuery but I don't see it in the Velocity code. You could pass the $core_v2_page.Url value as a parameter from the widget's Velocity script to the Javascript if it is a separate file. 

    Have you verified that the HTML and script are rendered correctly and without javascript errors?

    A few notes:

    • When rendering elements that your widget will interact with, it is best to scope your selectors either to the wrapping element ID ($core_v2_widget.WrapperElementId which is the ID of the DIV tag wrapping the content of the widget) or generate a unique ID for each interactive element ($core_v2_widget.UniqueId('country')).
    • When implementing AJAX requests, it is recommended to use a separate Velocity or server-side Javascript file to handle the callback which will be more efficient that posting back the entire document and includes security validation when used with $.telligent.evolution.post/put/del. See https://community.telligent.com/community/11/w/developer-training/65122/using-ajax#Custom_Widget-Defined_AJAX_Endpoints 
    • jQuery will provide the selected value of a select  box with just $('SELECT_BOX_SELECTOR').val() -- no need to filter by selected option.
Children
  • Former Member
    0 Former Member in reply to Ben Tiedt

    The Velocity and jQuery are in the same file. Here's the updated code:

    #set($countries = false)
    #set($countries = $Ibby_v1_LocationData.GetAllCountries())
    <form action="$core_v2_page.Url" method="post">
    #if ($countries)
    <div>
     <label>Country:</label>
                    <select class="country" name="countryname" id="$core_v2_widget.UniqueId('countryid')">
                        <option>Select</option>
                        #foreach ($country in $countries)
                            <option value="$country.iso2" #if ($core_v2_page.GetFormValue('countryname') == $country.iso2) selected #end>$country.country</option>
                        #end
                    </select>
    </div>
    #if ($core_v2_page.IsPost)
    #set($country = false)
    #set($country = $core_v2_page.GetFormValue('countryname'))
    #if ($country)
    
    #set($regions = $Ibby_v1_LocationData.GetRegionsInCountry($country))
    #if ($regions)
    <div>
    	    #if($country != 'Select')
            <label>Region:</label>
            <select name="regionname" id="$core_v2_widget.UniqueId('regionid')">
            <option>Select</option>
            #foreach($region in $regions)
                <option value="$region.admin_code" #if ($core_v2_page.GetFormValue('regionname') == $region.admin_code) selected #end>$region.admin_name</option>
            #end
            </select>
            #end
    </div>
    #end
    #set($region = false)
    #set($region = $core_v2_page.GetFormValue('regionname'))
    
    
    #set($cities = $Ibby_v1_LocationData.GetCitiesInRegion($country,$region))
    <div>
    	    #if($region != 'Select')
            <label>City:</label>
            <select id="$core_v2_widget.UniqueId('cityid')">
                <option>Select</option>
            #foreach($city in $cities)
                <option value="$city.Id">$city.city</option>
            #end
            </select>
            #end
    </div>
    
    #end
    #end
    #end    
    <button type="submit">Submit</button>
    </form>
    #registerEndOfPageHtml()
    	<script type="text/javascript">
    	$(document).ready(function() {
        $("select.country").change(function(){
            var selectedCountry = $(".country option:selected").val();
            $.ajax({
                type: "POST",
                url: "$core_v2_page.Url",
                data: { country : selectedCountry } 
            }).done(function(data){
                $("#response").html(data);
            });
        });
    });
    	</script>
    #end

    I tried to run the script separately in the Script Sandbox, but I got an error message saying "Line 1, Column 13: ReferenceError: document is not defined at call(Jint.Parser.Ast.ThisExpression) @ 0:1"

    The HTML/Velocity is rendered without errors.

  • Because this is all in one script executed as Velocity, the $ is interpreted by Velocity and may result in empty string replacements. When rendering calls to jQuery in Velocity, we recommend using jQuery instead of $.

    With that, the callback will execute, however, you have a few other issues:

    • Because you're posting back to the entire page, you're getting an entire page back (not likely what you expect). I recommend using the AJAX approach I mentioned in my earlier reply.
    • Your script is attempting to render the response into an element with ID response -- this element is not in your widget so it will not be displayed as written even after fixing the jQuery references.

    Regarding running the script sandbox -- it sounds like you were rendering it as server-side javascript, not Velocity. This is not written in server-side javascript, so you got an error. The AJAX callback would not work in the sandbox anyway because there is no context for posting back to (you'd be posting back to widget studio, which doesn't understand your request).