jQWidgets Forums

jQuery UI Widgets Forums Lists ComboBox Chained (Dependent) Combobox with XML data

This topic contains 7 replies, has 2 voices, and was last updated by  solveQueries 11 years, 6 months ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author

  • solveQueries
    Member

    I have the following XML for CountriesStatesCities

    <root>
    <country>
    <countryId>8</countryId>
    <countryName>Antarctica</countryName>
    <state>
    <city>
    <cityId>12976</cityId>
    <cityName>Molodesjnaja</cityName>
    </city>
    <city>
    <cityId>15188</cityId>
    <cityName>Reading</cityName>
    </city>
    <stateId>4761</stateId>
    <stateName>Enderby Land</stateName>
    </state>
    <state>
    <city>
    <cityId>14699</cityId>
    <cityName>McMurdo Station</cityName>
    </city>
    <stateId>4763</stateId>
    <stateName>Ross Island</stateName>
    </state>
    </country>
    ....
    </root>

    I have the following code for the dependent Country State City comboboxes:

        <script type="text/javascript">
    $(document).ready(function () {
    var url = "CountryStateCity.xml";
    var sourceCountries =
    {
    datatype: "xml",
    datafields: [
    { name: 'countryId', type: 'int' },
    { name: 'countryName', type: 'string' } ,
    { name: 'stateId', map: 'state>stateId', type: 'int' },
    { name: 'stateName', map: 'state>stateName', type: 'string' },
    { name: 'cityId', map: 'state>city>cityId', type: 'int' },
    { name: 'cityName', map: 'state>city>cityName', type: 'string' }
    ],
    root: "root",
    record: "country",
    url: url,
    async: false
    };
    var dataAdapterCountries = new $.jqx.dataAdapter(sourceCountries, { async: false });
    // states to display
    var statesToDisplay = new Array();
    // Create a jqxComboBox
    $("#jqxcombobox1").jqxComboBox({ source: dataAdapterCountries, displayMember: "countryName", valueMember: "countryId", width: '200px', height: '25px', dropDownHeight: '200px' });
    $('#jqxcombobox1').bind('select', function (event) {
    var selectedCountryId = event.args.item.value;
    //alert("Label: "+event.args.item.label+"\nValue: "+event.args.item.value+"\nIndex: "+event.args.item.index);
    var statesAdapter = new $.jqx.dataAdapter(sourceCountries, {
    autoBind: true,
    beforeLoadComplete: function (records) {
    var data = new Array();
    /*var StateIDToDisplay = new Array();
    var StateNameToDisplay = new Array();*/
    // update the loaded records. Dynamically add StateName and StateID fields.
    for (var i = 0; i < records.length; i++) {
    var countryRecord = records[i];
    if(countryRecord.countryId == selectedCountryId)
    {
    //alert(records[i]);
    //statesToDisplay [countryRecord.stateName] = countryRecord.stateId;
    countryRecord.StateIDToDisplay = countryRecord.stateId;
    countryRecord.StateNameToDisplay = countryRecord.stateName;
    data.push(countryRecord);
    /*StateIDToDisplay = countryRecord.stateId;
    StateNameToDisplay = countryRecord.stateName;*/
    }
    }
    return data;
    }
    });
    $("#jqxcombobox2").jqxComboBox({ source: statesAdapter, width: '200px', displayMember: "StateNameToDisplay", valueMember: "StateIDToDisplay", height: '25px', disabled: false });
    });
    });
    </script>
    </head>
    <body>
    <div id='content'>
    <div style="float: left;" id='jqxcombobox1'>
    </div>
    <div style="float: left;" id="jqxcombobox2">
    </div>
    <div style="float: left;" id="jqxcombobox3">
    </div>
    </div>
    </body>
    </html>

    My problem here is on selecting a country, all the states pertaining to that country is being populated on a single row. I think the dataAdapter represents all the child elements as a single entity.
    So is there any other way to access each sub-element of the entity i.e. one by one?


    Peter Stoev
    Keymaster

    Hi solveQueries,

    To process the “states” you will have to point to the “state” records when you define the “source” object’s “record” member.

    Example:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta name="keywords" content="jQuery jqxComboBox, List, ListBox, Popup List, jqxDropDownList, jqxListBox, List Widget, ListBox Widget, DropDownList Widget" />
    <meta name="description" content="The jqxDropDownList represents a widget that contains a list of selectable items." />
    <title id='Description'>In this demo the jqxComboBox is bound to XML data.</title>
    <link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" />
    <script type="text/javascript" src="../../scripts/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="../../scripts/demos.js"></script>
    <script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script>
    <script type="text/javascript" src="../../jqwidgets/jqxdata.js"></script>
    <script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script>
    <script type="text/javascript" src="../../jqwidgets/jqxscrollbar.js"></script>
    <script type="text/javascript" src="../../jqwidgets/jqxlistbox.js"></script>
    <script type="text/javascript" src="../../jqwidgets/jqxcombobox.js"></script>
    </head>
    <body>
    <div id='content'>
    <script type="text/javascript">
    $(document).ready(function () {
    var url = "text.xml";
    var sourceCountries =
    {
    datatype: "xml",
    datafields: [
    { name: 'stateId', map: 'stateId', type: 'int' },
    { name: 'stateName', map: 'stateName', type: 'string' },
    { name: 'cityId', map: 'city>cityId', type: 'int' },
    { name: 'cityName', map: 'city>cityName', type: 'string' }
    ],
    root: "root",
    record: "country>state",
    url: url,
    async: false
    };
    var dataAdapterCountries = new $.jqx.dataAdapter(sourceCountries, { async: false });
    $("#jqxWidget").jqxComboBox({ selectedIndex: 0, source: dataAdapterCountries, displayMember: "stateName", valueMember: "stateId", width: 200, height: 25 });
    });
    </script>
    <div id='jqxWidget'>
    </div>
    <div style="font-size: 12px; font-family: Verdana;" id="selectionlog"></div>
    </div>
    </body>
    </html>

    Here’s the sample file I tested with:

    <root>
    <country>
    <countryId>8</countryId>
    <countryName>Antarctica</countryName>
    <state>
    <city>
    <cityId>12976</cityId>
    <cityName>Molodesjnaja</cityName>
    </city>
    <city>
    <cityId>15188</cityId>
    <cityName>Reading</cityName>
    </city>
    <stateId>4761</stateId>
    <stateName>Enderby Land</stateName>
    </state>
    <state>
    <city>
    <cityId>14699</cityId>
    <cityName>McMurdo Station</cityName>
    </city>
    <stateId>4763</stateId>
    <stateName>Ross Island</stateName>
    </state>
    </country>
    <country>
    <countryId>9</countryId>
    <countryName>Antarctica 2</countryName>
    <state>
    <city>
    <cityId>12976</cityId>
    <cityName>Molodesjnaja 2</cityName>
    </city>
    <city>
    <cityId>15188</cityId>
    <cityName>Reading</cityName>
    </city>
    <stateId>4761</stateId>
    <stateName>Enderby Land 2</stateName>
    </state>
    <state>
    <city>
    <cityId>14699</cityId>
    <cityName>McMurdo Station 2</cityName>
    </city>
    <stateId>4763</stateId>
    <stateName>Ross Island 2</stateName>
    </state>
    </country>
    </root>

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com

    Chained (Dependent) Combobox with XML data #30746

    solveQueries
    Member

    Hi Peter,

    After pointing to the “state” records, I am not able to get the element to compare the selected countryId with the XML so that I could display the proper states within a country.

    Below is the code snippet used on the above XML:

        <script type="text/javascript">
    $(document).ready(function () {
    var url = "CountryStateCity.xml";
    var sourceCountries =
    {
    datatype: "xml",
    datafields: [
    { name: 'countryId', type: 'int' },
    { name: 'countryName', type: 'string' } ,
    { name: 'stateId', map: 'state>stateId', type: 'int' },
    { name: 'stateName', map: 'state>stateName', type: 'string' }
    ],
    root: "root",
    record: "country",
    url: url,
    async: false
    };
    var sourceStates =
    {
    datatype: "xml",
    datafields: [
    { name: 'countryId', type: 'int' },
    { name: 'countryName', type: 'string' } ,
    { name: 'stateId', map: 'state>stateId', type: 'int' },
    { name: 'stateName', map: 'state>stateName', type: 'string' },
    { name: 'cityId', map: 'state>city>cityId', type: 'int' },
    { name: 'cityName', map: 'state>city>cityName', type: 'string' }
    ],
    root: "root",
    record: "country>state",
    url: url,
    async: false
    };
    var dataAdapterCountries = new $.jqx.dataAdapter(sourceCountries, { async: false });
    // states to display
    var statesToDisplay = new Array();
    // Create a jqxComboBox
    $("#jqxcombobox1").jqxComboBox({ source: dataAdapterCountries, displayMember: "countryName", valueMember: "countryId", placeHolder: "Select Country...", width: '200px', height: '25px', dropDownHeight: '200px' });
    $('#jqxcombobox1').bind('select', function (event) {
    var selectedCountryId = event.args.item.value;
    var dataAdapterStates = new $.jqx.dataAdapter(sourceStates, {
    autoBind: true,
    beforeLoadComplete: function (records) {
    var data = new Array();
    for (var i = 0; i < records.length; i++) {
    var countryRecord = records[i];
    if(countryRecord.countryId == selectedCountryId)
    {
    countryRecord.StateIDToDisplay = countryRecord.stateId;
    countryRecord.StateNameToDisplay = countryRecord.stateName;
    data.push(countryRecord);
    }
    }
    return data;
    }
    });
    $("#jqxcombobox2").jqxComboBox({ source: dataAdapterStates, width: '200px', displayMember: "StateNameToDisplay", valueMember: "StateIDToDisplay", placeHolder: "Select State...",height: '25px', disabled: false });
    });
    });
    </script>
    </head>
    <body>
    <div id='content'>
    <div style="float: left;" id='jqxcombobox1'>
    </div>
    <div style="float: left;" id="jqxcombobox2">
    </div>
    <div style="float: left;" id="jqxcombobox3">
    </div>
    </div>
    </body>
    </html>

    On this line

    if(countryRecord.countryId == selectedCountryId)

    I am not able to get the countryId from dataAdapterStates.

    Need some help to display the states contained in a particular country.

    Chained (Dependent) Combobox with XML data #30749

    Peter Stoev
    Keymaster

    Hi solveQueries,

    The sample I sent you shows how to get the “States” in your XML and nothing else. “countryID” and “countryName” should not be part of the “sourceStates ” object.

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com

    Chained (Dependent) Combobox with XML data #30751

    solveQueries
    Member

    Hi Peter,

    I agree with your point, but as I said in my first post I want a chained ComboBox and I guess the only way to do this is by above method. So could you help me generate a chained combo-box.

    Thanks!


    Peter Stoev
    Keymaster

    Hi solveQueries,

    According to me, you will have to do some custom processing in the downloadComplete callback of the first dataAdapter. There you will get the Raw data downloaded from the XML. By doing that you should be able to get the required records for displaying into the ComboBoxes.

    Best Regards,
    Peter Stoev

    jQWidgets Team
    http://www.jqwidgets.com


    solveQueries
    Member

    Hi Peter,

    Ok. Trying out downloadComplete callback way. Will inform when its done


    solveQueries
    Member

    Hi Peter,

    Below is code I used to achieve chained ComboBox. I have used the jQuery GET method to read the xml & store the data in an variable. But here I am reading the XML twice, once through jQuery GET method & second through dataAdapterCountries.

    <script type="text/javascript">
    $(document).ready(function () {
    var url = "CountryStateCity.xml";
    var all_data = null;
    $.get(url, function(data) { // get the countryStateCity.xml file
    all_data = data; // save the data for future use
    }, 'xml'); // specify what format the request will return - XML
    var sourceCountries =
    {
    datatype: "xml",
    datafields: [
    { name: 'countryId', type: 'int' },
    { name: 'countryName', type: 'string' }
    ],
    root: "root",
    record: "country",
    url: url,
    async: false
    };
    var dataAdapterCountries = new $.jqx.dataAdapter(sourceCountries, { async: false });
    // Create a COUNTRY jqxComboBox
    $("#jqxcombobox1").jqxComboBox({ source: dataAdapterCountries, displayMember: "countryName", valueMember: "countryId", placeHolder: "Select Country...", width: '200px', height: '25px', dropDownHeight: '200px' });
    $("#jqxcombobox2").jqxComboBox({ disabled: true, placeHolder: "Select State..." });
    $("#jqxcombobox3").jqxComboBox({ disabled: true, placeHolder: "Select City..." });
    $('#jqxcombobox1').bind('select', function (event) {
    var statesToDisplay = new Array();
    var selectedCountryId = event.args.item.value;
    i=0;
    $('country', all_data).filter(function() { // get all countries from xml
    return selectedCountryId == $(this).find("countryId").text();
    }).find('state').each(function() {
    var row = {};
    row['stateName'] = $(this).find("stateName").text();
    row['stateId'] = $(this).find("stateId").text();
    statesToDisplay[i] = row;
    i++;
    });
    var stateSource = {
    datatype: "array",
    datafields: [
    { name: 'stateName', type: 'string'},
    { name: 'stateId', type: 'int'}
    ],
    localdata: statesToDisplay
    };
    var dataAdapterStates = new jQuery.jqx.dataAdapter(stateSource, { async: false });
    $("#jqxcombobox2").jqxComboBox({ source: dataAdapterStates, width: '200px', displayMember: "stateName", valueMember: "stateId", placeHolder: "Select State...", height: '25px', disabled: false });
    });
    $('#jqxcombobox2').bind('select', function (event) {
    var citiesToDisplay = new Array();
    var selectedStateId = event.args.item.value;
    i=0;
    $('state', all_data).filter(function() { // get all states from xml
    return selectedStateId == $(this).find("stateId").text();
    }).find('city').each(function() {
    var row = {};
    row['cityName'] = $(this).find("cityName").text();
    row['cityId'] = $(this).find("cityId").text();
    citiesToDisplay[i] = row;
    i++;
    });
    var citySource = {
    datatype: "array",
    datafields: [
    { name: 'cityName', type: 'string'},
    { name: 'cityId', type: 'int'}
    ],
    localdata: citiesToDisplay
    };
    var dataAdapterCities = new jQuery.jqx.dataAdapter(citySource, { async: false });
    $("#jqxcombobox3").jqxComboBox({ source: dataAdapterCities, width: '200px', displayMember: "cityName", valueMember: "cityId", placeHolder: "Select City...", height: '25px', disabled: false });
    });
    });
    </script>
    </head>
    <body>
    <div id='content'>
    <div style="float: left;" id='jqxcombobox1'>
    </div>
    <div style="float: left;" id="jqxcombobox2">
    </div>
    <div style="float: left;" id="jqxcombobox3">
    </div>
    </div>
    </body>
    </html>

    Is there a more efficient way to read that XML only once & do all the processing thereafter, since the size of the XML being used by me is 4.5 MB which is too large to read twice?

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.