Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

MVC Jquery Mobile Remote Autocomplete problem...

Options
  • 20-01-2017 2:07am
    #1
    Closed Accounts Posts: 242 ✭✭


    Hi folks,

    I'm trying to implement this on my website:

    http://demos.jquerymobile.com/1.4.5/listview-autocomplete-remote/

    I'm trying to get exactly that solution implemented but I can't get it to run.


    I then want to modify the code to use access a list of unique product stock codes that is held on a table on my MS SQL database, using my MVC model & controller...

    [HTML]
    @Scripts.Render("~/bundles/modernizr")

    <link rel="stylesheet" href="~/Content/themes/Hello.css" />
    <link rel="stylesheet" href="~/Content/themes/jquery.mobile.icons.min.css" />
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile.structure-1.4.5.min.css&quot; />
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script&gt;
    <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script&gt;
    <script src="jqm.autoComplete-1.4.5-min.js"></script>
    <link href="~/Content/mobile/css/style.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript">
    $(document).on("Autocomplete", "#Autocomplete", function () {
    $("#Autocomplete").on("filterablebeforefilter", function (e, data) {
    var $ul = $(this),
    $input = $(data.input),
    value = $input.val(),
    html = "";
    $ul.html("");
    if (value && value.length > 2) {
    $ul.html("<li><div class='ui-loader'><span class='ui-icon ui-icon-loading'></span></div></li>");
    $ul.listview("refresh");
    $.ajax({
    url: "http://gd.geobytes.com/AutoCompleteCity",
    dataType: "jsonp",
    crossDomain: true,
    data: {
    q: $input.val()
    }
    })
    .then(function (response) {
    $.each(response, function (i, val) {
    html += "<li>" + val + "</li>";
    });
    $ul.html(html);
    $ul.listview("refresh");
    $ul.trigger("updatelayout");
    });
    }
    });
    });
    </script>
    <link rel="stylesheet" href="/Content/style.css" />

    </head>
    <body>
    <style>
    .ui-filter-inset {
    margin-top: 0;
    }
    </style>
    <div data-role="page" id="Autocomplete">
    <h3>Cities worldwide</h3>
    <p>After you enter <strong>at least three characters</strong> the autocomplete function will show all possible matches.</p>
    <form class="ui-filterable">
    <input id="autocomplete-input" data-type="search" placeholder="Find a city...">
    </form>
    <ul id="autocomplete" data-role="listview" data-inset="true" data-filter="true" data-input="#autocomplete-input"></ul>
    </div>
    </body>
    </html>
    [/HTML]

    I've developed using C# and HTML, I've recently learnt how to use jquery mobile collapsibles but am having trouble integrating the above functionality into my website...

    Grateful in advance for any help with this, I've very very little JS experience!


Comments

  • Closed Accounts Posts: 242 ✭✭Divelment


    Hi folks,

    Just an update, I got the first part of my problem sorted, as in I have the JQM Autocomplete running properly now on my Visual Studio 2015 Community here. This is the code that has it working now, but could someone maybe advise me on how I go about modify the JS code to pull data from my MS SQL server DB based on the search box text, as opposed to pulling the data from Google?

    Many thanks in advance for any help with this!

    D.

    Working code below:

    [HTML]
    @{
    Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
    <meta name="viewport" content="width=device-width" />
    <title>Autocomplete</title>

    @Styles.Render("~/Content/mobileCss", "~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

    <link rel="stylesheet" href="~/Content/themes/Hello.css" />
    <link rel="stylesheet" href="~/Content/themes/jquery.mobile.icons.min.css" />
    <link href="~/Content/mobile/css/style.css" rel="stylesheet" type="text/css" />

    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile.structure-1.4.5.min.css&quot; />
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script&gt;
    <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script&gt;

    <script>
    $( document ).on( "pagecreate", "#myPage", function() {
    $( "#autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
    var $ul = $( this ),
    $input = $( data.input ),
    value = $input.val(),
    html = "";
    $ul.html( "" );
    if ( value && value.length > 2 ) {
    $ul.html( "<li><div class='ui-loader'><span class='ui-icon ui-icon-loading'></span></div></li>" );
    $ul.listview( "refresh" );
    $.ajax({
    url: "http://gd.geobytes.com/AutoCompleteCity",
    dataType: "jsonp",
    crossDomain: true,
    data: {
    q: $input.val()
    }
    })
    .then( function ( response ) {
    $.each( response, function ( i, val ) {
    html += "<li>" + val + "</li>";
    });
    $ul.html( html );
    $ul.listview( "refresh" );
    $ul.trigger( "updatelayout");
    });
    }
    });
    });
    </script>
    <style>
    .ui-filter-inset {
    margin-top: 0;
    }
    </style>

    </head>
    <body>
    <style>
    .ui-filter-inset {
    margin-top: 0;
    }
    </style>
    <div data-role="page" class="jqm-demos" id="myPage">

    <div data-role="header" class="jqm-header">
    <h2><a href="../" title="jQuery Mobile Demos home"><img src="../_assets/img/jquery-logo.png" alt="jQuery Mobile"></a></h2>
    <p><span class="jqm-version"></span> Demos</p>
    <a href="#" class="jqm-navmenu-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-bars ui-nodisc-icon ui-alt-icon ui-btn-left">Menu</a>
    <a href="#" class="jqm-search-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-search ui-nodisc-icon ui-alt-icon ui-btn-right">Search</a>
    </div><!-- /header -->

    <div role="main" class="ui-content jqm-content">

    <h1>Remote autocomplete</h1>

    <p>To create an autocomplete that uses a remote data source, you can use the <code>filterablebeforefilter</code> event of the Filterable widget to dynamically populate a listview as a user types a search query.</p>

    <p>This is useful when you have a very large data set like cities, zip codes, or products that can't be loaded up-front locally. Use the view source button to see the JavaScript that powers this demo.</p>
    <p>If you have a small list of items, you can use the filter reveal option to make an <a href="../listview-autocomplete/">autocomplete with local listview data</a>.</p>

    <div data-demo-html="true" data-demo-js="true" data-demo-css="true">
    <h3>Cities worldwide</h3>
    <p>After you enter <strong>at least three characters</strong> the autocomplete function will show all possible matches.</p>
    <form class="ui-filterable">
    <input id="autocomplete-input" data-type="search" placeholder="Find a city...">
    </form>
    <ul id="autocomplete" data-role="listview" data-inset="true" data-filter="true" data-input="#autocomplete-input"></ul>
    </div><!--/demo-html --></div>
    </body>
    </html>

    [/HTML]


  • Registered Users Posts: 586 ✭✭✭Aswerty


    It's very simple from the client side to change where you source the data. We just update the url parameter in the object we pass to the $.ajax() function.
    $.ajax({
        url: "http://yourdomain.com/AutoComplete",
        dataType: "jsonp",
        crossDomain: true,
        data: {
            q: $input.val()
        }
    })
    

    We've updated the url from geobytes.com to yourdomain.com (this will most likely be localhost for testing purposes). And that looks to be the only necessary change on the client side.

    The main piece of work here is to build an action method that returns the correct values in the correct format. You have to route yourdomain.com/AutoComplete to this new action method either via the routing class or by conventions that are already in place (e.g. naming the action method AutoComplete and so on).

    When I was testing the autocomplete, I saw that it passes 3 parameters back to the server: callback, q, and _. We can see this in this example URL request.
    http://gd.geobytes.com/AutoCompleteCity?callback=jQuery110206170137703450915_1484932436245&q=new&_=1484932436247
    

    And we see the response from the server as so.
    jQuery110206170137703450915_1484932436245(["New Albany, IN, United States","New Albany, KS, United States","New Albany, MS, United States","New Albany, OH, United States","New Albany, PA, United States","New Albin, IA, United States","New Alexandria, PA, United States","New Almaden, CA, United States","NEW AMSTERDAM, EB, Guyana","New Athens, IL, United States","New Athens, OH, United States","New Auburn, MN, United States","New Auburn, WI, United States","New Augusta, MS, United States","New Baden, IL, United States","New Baden, TX, United States","New Baltimore, MI, United States","New Baltimore, NY, United States","New Baltimore, PA, United States","New Bavaria, OH, United States"]);
    

    So from this we can understand that jQuery expects you to respond, via your action method, with a stringified callback method (which has a strong unique id for security purposes) whose name is equal to the callback parameter. This callback is passed an array of strings where each string corresponds to a distinct entry in the remote list the user sees.

    The following is an example of an action method that could respond to the remote caller.
    public ActionResult AutoComplete(string callback, string q)
    {
        // you'd use q (the query the user types into the jQuery component) to search the database for the right stock codes
    
        string[] cities = new string { "Dublin", "Cork", "Galway", "Limerick", "Waterford is not a city!!!" };
        return Content(string.Format("{0}([\"{1}\"]);", callback, string.Join("\", \"", cities)), "application/json");
    }
    

    Note that this is some hacked together code (also returning a ContentResult is a bit of a mess, you'd probably be better off returning a JsonResult) to respond in a way the remote caller understands. You should be able to exchange my code for you own code that pulls data from your database.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Thanks so much for that Aswerty, is it as simple to modify the code so that the any one result in the list view can be selected? Like to make the list returned selectable?


  • Registered Users Posts: 586 ✭✭✭Aswerty


    Not quite following what you're asking there, so the following might be a bit wide of the mark...

    It shouldn't matter what list you return, the jQuery component looks to be agnostic as to what type of data it gets (as long as it's a string). So it should handle selecting a stock code, in the same manner it handles selecting the cities, without any modification. Thus the only work on your part is on the server side.

    Oh, and I just updated the ActionMethod example in my last post since I had ignored the query parameter (q). Maybe the lack of an example of what you do with the query was causing you to think something extra needed to be done on the client side. The query passed back should be used to build a DB query which gets a list of ten or so stock codes the user might wish to select.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    Not quite following what you're asking there, so the following might be a bit wide of the mark...

    It shouldn't matter what list you return, the jQuery component looks to be agnostic as to what type of data it gets (as long as it's a string). So it should handle selecting a stock code, in the same manner it handles selecting the cities, without any modification. Thus the only work on your part is on the server side.

    Oh, and I just updated the ActionMethod example in my last post since I had ignored the query parameter (q). Maybe the lack of an example of what you do with the query was causing you to think something extra needed to be done on the client side. The query passed back should be used to build a DB query which gets a list of ten or so stock codes the user might wish to select.

    No I get what you are saying there. My question is regarding the following solution offered by JQM:

    http://demos.jquerymobile.com/1.3.1/widgets/autocomplete/autocomplete-remote.html

    If you have a look at that solution, it doesn't let the user click on any of the results returned, in that the results list is not selectable, I'm trying to get a solution in place on my site that is selectable, so you click on the option retiurned that you are searching for, and the data from that row is put into the textbox or into another label or whatever works best...

    My problem is that I'm able to develop in C# and am able to use MVC but I've no exposure to JS, which I know I should do something about lol!


  • Advertisement
  • Registered Users Posts: 586 ✭✭✭Aswerty


    If you've no exposure to JS that prove quite a barrier. What you're asking after doesn't really have anything to do with the jQuery component anymore. Once those stock codes are getting listed you need to write JS code that treats them the same way you would any other html element on the page.

    A rough guide to what you'd want to do is:
    • Create an onclick event for the elements in the list of the jQuery component (i.e. $('#autocomplete > li').onclick(event))
    • Then from the event you'd access the stock code.
    • Then you'd be free to assign the stock code to another element, be that a text box or whatever.

    I think you really need to delve into JS and jQuery if you want to progress with dynamic web pages.


  • Closed Accounts Posts: 242 ✭✭Divelment


    I'm having an issue with my original autocomplete query. I've written a controller method that brings back the data as per my query (it's working off a vehicle reg ID), the method is bringing back the data as per the query but the data isn't finding its way into my view and my Json it would seem...

    I've put a breakpoint in my code and I can see the data in the controller data query...

    Here's my controller code:

    [HTML]
    public ActionResult AutocompleteData(string callback, string q)
    {

    string QueryStatus = "Query";

    var context = new GarageViewModelDBContext(); //consider having this injected into your constructor but lets keep it simple for now

    //var products = context.VehicleDBs.Where(p => p.UserID == UserId);

    var query = context.VehicleDBs.Where(n => n.VehicleID.ToUpper().Contains(q.ToUpper()));

    if (!string.IsNullOrEmpty(q))
    {


    query = query.Where(p => p.Status == QueryStatus);
    query = query.OrderByDescending(p => p.ID);


    }

    var MyContent = query.ToList(); //this executes your query and retrieves the results into memory

    return Json(query, JsonRequestBehavior.AllowGet);
    //return Json(string.Format("{0}([\"{1}\"]);", callback, string.Join("\", \"", query)), JsonRequestBehavior.AllowGet);


    }

    [/HTML]

    I'm suspecting that there are more fields in my DB table than I have procided for in my Autocomplete IS/html code, but don't know how to fix that.


    And my view code:

    [HTML]
    @{
    Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
    <meta name="viewport" content="width=device-width" />
    <title>Autocomplete</title>

    @Styles.Render("~/Content/mobileCss", "~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

    <link rel="stylesheet" href="~/Content/themes/Hello.css" />
    <link rel="stylesheet" href="~/Content/themes/jquery.mobile.icons.min.css" />
    <link href="~/Content/mobile/css/style.css" rel="stylesheet" type="text/css" />

    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile.structure-1.4.5.min.css&quot; />
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script&gt;
    <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script&gt;

    <script>
    $( document ).on( "pagecreate", "#myPage", function() {
    $( "#autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
    var $ul = $( this ),
    $input = $( data.input ),
    value = $input.val(),
    html = "";
    $ul.html("");

    if ( value && value.length > 2 ) {
    $ul.html( "<li><div class='ui-loader'><span class='ui-icon ui-icon-loading'></span></div></li>" );
    $ul.listview( "refresh" );
    $.ajax({
    //url: "http://gd.geobytes.com/AutoCompleteCity",
    //url: "http://localhost:52650/home/autocompleteData",
    '@Url.Action("AutocompleteData", "Home")',

    dataType: "jsonp",
    crossDomain: true,
    data: {
    q: $input.val()
    }

    }

    )

    .then( function ( response ) {
    $.each( response, function ( i, val ) {
    html += "<li>" + val + "</li>";
    });
    $ul.html( html );
    $ul.listview( "refresh" );
    $ul.trigger("updatelayout");


    });

    }
    });
    });
    </script>
    <style>
    .ui-filter-inset {
    margin-top: 0;
    }
    </style>

    </head>
    <body>
    <style>
    .ui-filter-inset {
    margin-top: 0;
    }
    </style>
    <div data-role="page" class="jqm-demos" id="myPage">

    <div data-role="header" class="jqm-header">
    <h2><a href="../" title="jQuery Mobile Demos home"><img src="../_assets/img/jquery-logo.png" alt="jQuery Mobile"></a></h2>
    <p><span class="jqm-version"></span> Demos</p>
    <a href="#" class="jqm-navmenu-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-bars ui-nodisc-icon ui-alt-icon ui-btn-left">Menu</a>
    <a href="#" class="jqm-search-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-search ui-nodisc-icon ui-alt-icon ui-btn-right">Search</a>
    </div><!-- /header -->

    <div role="main" class="ui-content jqm-content">

    <h1>Remote autocomplete</h1>

    <p>To create an autocomplete that uses a remote data source, you can use the <code>filterablebeforefilter</code> event of the Filterable widget to dynamically populate a listview as a user types a search query.</p>

    <p>This is useful when you have a very large data set like cities, zip codes, or products that can't be loaded up-front locally. Use the view source button to see the JavaScript that powers this demo.</p>
    <p>If you have a small list of items, you can use the filter reveal option to make an <a href="../listview-autocomplete/">autocomplete with local listview data</a>.</p>

    <div data-demo-html="true" data-demo-js="true" data-demo-css="true">
    <h3>Cities worldwide</h3>
    <p>After you enter <strong>at least three characters</strong> the autocomplete function will show all possible matches.</p>
    <form class="ui-filterable">
    <input id="autocomplete-input" data-type="search" placeholder="Find a city...">
    </form>
    <ul id="autocomplete" data-role="listview" data-inset="true" data-filter="true" data-input="#autocomplete-input"></ul>
    </div><!--/demo-html --></div></div>
    </body>
    </html>

    [/HTML]

    EDIT: I've fiddled around with the code trying to get it to work, with this at the bottom of my controller method:

    [HTML]

    var MyContent = query.ToList(); //this executes your query and retrieves the results into memory

    return Json(query, JsonRequestBehavior.AllowGet);
    //return Json(string.Format("{0}([\"{1}\"]);", callback, string.Join("\", \"", query)), JsonRequestBehavior.AllowGet);
    [/HTML]


  • Closed Accounts Posts: 242 ✭✭Divelment


    EDIT, apologies again, I've had to change:

    [HTML]
    //url: "http://gd.geobytes.com/AutoCompleteCity",
    //url: "http://localhost:52650/home/autocompleteData",
    '@Url.Action("AutocompleteData", "Home")',
    [/HTML]

    To...

    //url: "http://gd.geobytes.com/AutoCompleteCity",
    url: "http://localhost:52650/home/autocompleteData",
    //'@Url.Action("AutocompleteData", "Home")',

    To get the data to come back from the server...


  • Registered Users Posts: 586 ✭✭✭Aswerty


    If you go back to my first response and look at the server response example (e.g. jquery11020617....) the response you are generating looks nothing like that. This is because you're just shoving the list of Vehicle objects into a JsonResult, you should be selecting the individual property that you want to list in the AutoComplete component. So for example the following would get you the specific data you want to return.
        var MyContent = query.Select(x => x.VehicleID).ToList();
    

    Also don't forget the AutoComplete component seems to expect you to have the callback parameter as part of the response. And actually if that callback parameter is included the response isn't actually valid JSON; it's actually just stringified JavaScript (which seem a bit odd to me but that's what it expects). The jQuery UI docs don't actually detail what a valid response actually consists of so I'm just relying on the response I see in their example page. So ultimately, if you need to return the list of data as a parameter inside the callback function you might be better off using the ContentResult rather than the JsonResult because you're crafting invalid JSON.

    If I was you I'd just build a valid response and not worry about what kind of data I'm sending back - just to validate things are working. So I'd probably just return something akin to the following:
    string response = callback + "([\"Result 1\",\"Result 2\"]);";
    return Content(response, "application/json");
    

    Once you have the above working in AutoComplete then you can look at reworking the solution to return your VehicleID values.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    If you go back to my first response and look at the server response example (e.g. jquery11020617....) the response you are generating looks nothing like that. This is because you're just shoving the list of Vehicle objects into a JsonResult, you should be selecting the individual property that you want to list in the AutoComplete component. So for example the following would get you the specific data you want to return.
        var MyContent = query.Select(x => x.VehicleID).ToList();
    
    Also don't forget the AutoComplete component seems to expect you to have the callback parameter as part of the response. And actually if that callback parameter is included the response isn't actually valid JSON; it's actually just stringified JavaScript (which seem a bit odd to me but that's what it expects). The jQuery UI docs don't actually detail what a valid response actually consists of so I'm just relying on the response I see in their example page. So ultimately, if you need to return the list of data as a parameter inside the callback function you might be better off using the ContentResult rather than the JsonResult because you're crafting invalid JSON.

    If I was you I'd just build a valid response and not worry about what kind of data I'm sending back - just to validate things are working. So I'd probably just return something akin to the following:
    string response = callback + "([\"Result 1\",\"Result 2\"]);";
    return Content(response, "application/json");
    
    Once you have the above working in AutoComplete then you can look at reworking the solution to return your VehicleID values.

    Thanks a mil for clearing all this up for me, I'm just not sure what I should change Result 1 and Result 2 in the above, into for my solution. Is the var MyContent what I should be putting in for Result 1?


  • Advertisement
  • Closed Accounts Posts: 242 ✭✭Divelment


    Lovely stuff, for the first time I have my Autocomplete bringing back and displaying data from my server!

    I've used this code you gave me before:

    [HTML]

    var MyContent = query.Select(x => x.VehicleID).ToList();

    return Content(string.Format("{0}([\"{1}\"]);", callback, string.Join("\", \"", MyContent)), "application/json");[/HTML]


  • Closed Accounts Posts: 242 ✭✭Divelment


    I'd love to get back another field though, but am not getting it right with the below:

    [HTML]

    var MyContent = query.Select(x => x.VehicleID).ToList();
    var MyMake = query.Select(x => x.ProductSolution).ToList();


    return Content(string.Format("{0}([\"{1}\", \"{2}\"]); ", callback, string.Join("\", \"", MyContent, MyMake)), "application/json");

    [/HTML]


  • Registered Users Posts: 586 ✭✭✭Aswerty


    Congrats on getting your server returning data.

    As to your new issue. The return line is becoming a bit of a mess (between the escaped quotes, string.Join(), and string.Format() it's hard to follow). Through the use of the Union method you can merge the two lists so you can keep your return line the same as when you had it working. Below is a tied up version that uses Union.
    var myContent = query.Select(x => x.VehicleID).ToList();
    var myMake = query.Select(x => x.ProductSolution).ToList();
    var mergedContent = myContent.Union(myMake);
    var stringifiedContent = string.Join("\", \"", mergedContent);
    var response = string.Format("{0}([\"{1}\"]);", callback, stringifiedContent)
    
    return Content(response, "application/json");
    

    If the VehicleID and ProductSolution are different types. Just use ToString to convert the non-strings into strings (e.g. x => x.VehicleID.ToString()).


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    Congrats on getting your server returning data.

    As to your new issue. The return line is becoming a bit of a mess (between the escaped quotes, string.Join(), and string.Format() it's hard to follow). Through the use of the Union method you can merge the two lists so you can keep your return line the same as when you had it working. Below is a tied up version that uses Union.
    var myContent = query.Select(x => x.VehicleID).ToList();
    var myMake = query.Select(x => x.ProductSolution).ToList();
    var mergedContent = myContent.Union(myMake);
    var stringifiedContent = string.Join("\", \"", mergedContent);
    var response = string.Format("{0}([\"{1}\"]);", callback, stringifiedContent)
    
    return Content(response, "application/json");
    
    If the VehicleID and ProductSolution are different types. Just use ToString to convert the non-strings into strings (e.g. x => x.VehicleID.ToString()).

    Thanks so much with the help with this, I made the changes above but still can't get it to display more than one column of data from my DB.

    The "union" command also seems to be changing the data that is displayed, for example, where I'd expect to see 6 rows of data which is coming back under the first way I tried it (without trying to add a second column of data from my DB), using this updated method, I'm only getting back one row of data?

    Here's what's going on:

    This is what is in my response when I use a break point at the end of my controller method:

    407594.png


    This is my response on the front end:

    407595.png

    And this is how my response looks in the HTML visualizer tool on MS Visual Community:

    407596.png

    :confused::confused::confused: Do I need to make some change to me JS code or something?


  • Registered Users Posts: 586 ✭✭✭Aswerty


    You might have sorted things out already, but in case not...

    It looks like the widget still applies a filter when you load data remotely. So instead of returning SEAT you might return 06D99999 since it's a real match (does it even make sense to return anything that doesn't match what the user inputs?). So only returning real matches for 06D we can stop the filter from having an effect.

    Alternatively, you can setup logic for how the autocomplete filters on the browser side. Without a sandbox to test custom values being returned I'm not sure how correct this is:
    $( "#autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
    
    	e.preventDefault();
        
            // the rest of your code
    });
    

    By the looks of it, preventing the default functionality from performing on the event stops any client side filtering.

    It looks like there is plenty of options for overriding the client side filtering.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    You might have sorted things out already, but in case not...

    It looks like the widget still applies a filter when you load data remotely. So instead of returning SEAT you might return 06D99999 since it's a real match (does it even make sense to return anything that doesn't match what the user inputs?). So only returning real matches for 06D we can stop the filter from having an effect.

    Alternatively, you can setup logic for how the autocomplete filters on the browser side. Without a sandbox to test custom values being returned I'm not sure how correct this is:
    $( "#autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
    
    	e.preventDefault();
        
            // the rest of your code
    });
    

    By the looks of it, preventing the default functionality from performing on the event stops any client side filtering.

    It looks like there is plenty of options for overriding the client side filtering.

    Hiya Aswerty, still haven't got this sorted yet but will try that fix later... can ye see what I'm doing wrong this is stopping me from displaying more than one data field?


  • Registered Users Posts: 586 ✭✭✭Aswerty


    Hey,

    If your query is "06D" then any result returned that doesn't start with that term will be filtered by the AutoCompelte component. My preventDefault() change should hopefully rectify that, but as I said since I don't have a remote data source to play with I can't verify that but that's what the docs seem to recommend. So ultimately if you return a bunch of data but only one starts with "06D" - under your current approach - you'd only see that one row.

    I know you were having a bit of an issue implementing the Union method but you seem to have enough chops vis-a-vis C# that you should be able to get the merging of two list working yourself. It's worth pointing out that any database column other than the vehicle reg in all likelihood won't have data that starts with "06D". This would mean that the AutoComplete would filter it out so you wouldn't see it. Hopefully my proposed change will rectify that. Once again though, I'm not sure how much sense it is to return a list of makes when the user is typing in a reg.

    It's also worth pointing out that Union gets rid of non-unique fields. So if one list contains repeating vehicle regs it'll remove the duplicate data. A basic way to avoid this is to replace Union with a foreach loop that iterates through myMake and on each iteration adds the value to the myContent list.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    Hey,

    If your query is "06D" then any result returned that doesn't start with that term will be filtered by the AutoCompelte component. My preventDefault() change should hopefully rectify that, but as I said since I don't have a remote data source to play with I can't verify that but that's what the docs seem to recommend. So ultimately if you return a bunch of data but only one starts with "06D" - under your current approach - you'd only see that one row.

    I know you were having a bit of an issue implementing the Union method but you seem to have enough chops vis-a-vis C# that you should be able to get the merging of two list working yourself. It's worth pointing out that any database column other than the vehicle reg in all likelihood won't have data that starts with "06D". This would mean that the AutoComplete would filter it out so you wouldn't see it. Hopefully my proposed change will rectify that. Once again though, I'm not sure how much sense it is to return a list of makes when the user is typing in a reg.

    It's also worth pointing out that Union gets rid of non-unique fields. So if one list contains repeating vehicle regs it'll remove the duplicate data. A basic way to avoid this is to replace Union with a foreach loop that iterates through myMake and on each iteration adds the value to the myContent list.

    I copped was was going on with union, I replaced it with concat and the data that was returned changed to what I was hoping that get back. I'm only going back at this after a year away from software so thanks for your patience with me on this! Will try all the above tonight when I get home, huge thanks again!


  • Registered Users Posts: 586 ✭✭✭Aswerty


    Divelment wrote: »
    I copped was was going on with union, I replaced it with concat and the data that was returned changed to what I was hoping that get back. I'm only going back at this after a year away from software so thanks for your patience with me on this! Will try all the above tonight when I get home, huge thanks again!

    I didn't even know linq had a Concat method. Union typically serves me well, you learn something new everyday!


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    I didn't even know linq had a Concat method. Union typically serves me well, you learn something new everyday!

    FML, spent the whole day trying to get this to work out and it's just not happening, this thing of trying to display a 2nd (or more) column of data per row on my Listview that is returned by autocomplete!

    The problem as far as I can work out, seems to be this... When I concat or use union to join/mash the two strings, it just mashs the total contents of both strings together. From what I can see here, the data needs to be in a certain format, which is:

    [HTML]jQuery110206170137703450915_1484932436245(["New Albany, IN, United States","New Albany, KS, United States","New Albany, MS, United States","New Albany, OH, United States","New Albany, PA, United States","New Albin, IA, United States","New Alexandria, PA, United States","New Almaden, CA, United States","NEW AMSTERDAM, EB, Guyana","New Athens, IL, United States","New Athens, OH, United States","New Auburn, MN, United States","New Auburn, WI, United States","New Augusta, MS, United States","New Baden, IL, United States","New Baden, TX, United States","New Baltimore, MI, United States","New Baltimore, NY, United States","New Baltimore, PA, United States","New Bavaria, OH, United States"]);[/HTML]

    Basically for each row of data that gets displayed, the format must be:

    [HTML]
    "Row1Column1Ddata, Row1Column2Data, Row1Column3Data", "Row2Column1Ddata, Row2Column2Data, Row2Column3Data",
    [/HTML]

    As per the solution that I've used, the format doesn't look right, I'm getting back in my response:

    407594.png

    Is this making any sense, the way I'm explaining this? Basically I think I have two sets of quotes "...", where everything should be inside one set of double quotes???


  • Advertisement
  • Registered Users Posts: 586 ✭✭✭Aswerty


    I think I've only worked out that you want to put the vehicle make after the registration on the same row. I had been very confused as to why you wanted to have the make as a separate result - your desired result seems rather obvious now but it was going right over my head.

    Try something like:
    // we combine the reg and make into a single result as part of the LINQ expression
    var myContent = query.Select(x => x.VehicleID + " " + x.VehicleMake).ToList();
    var stringifiedContent = string.Join("\", \"", myContent);
    var response = string.Format("{0}([\"{1}\"]);", callback, stringifiedContent)
    
    return Content(response, "application/json");
    

    So yes you're right, you should have everything for a single result inside one double quote. A set of double quotes in your response is how you encapsulate data as a single result. The AutoComplete widget doesn't have any concept of columns, I was a bit confused as to why you kept referring to them. The reason the example data has comma seperated values is that that is the format for addresses. So the commas in "New Albany, IN, United States" are just part of the content for the result, they aren't an indication of separate columns of data. Likewise, you would probably separate the vehicle reg from the make with a comma but you could put the make in curved brackets or do any other kind of grammatical separation such as using a pipe or hyphen.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Gonna try this now, sorry I wasn't more clear on what I was trying to get implemented re additional columns!


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    I think I've only worked out that you want to put the vehicle make after the registration on the same row. I had been very confused as to why you wanted to have the make as a separate result - your desired result seems rather obvious now but it was going right over my head.

    Try something like:
    // we combine the reg and make into a single result as part of the LINQ expression
    var myContent = query.Select(x => x.VehicleID + " " + x.VehicleMake).ToList();
    var stringifiedContent = string.Join("\", \"", myContent);
    var response = string.Format("{0}([\"{1}\"]);", callback, stringifiedContent)
    
    return Content(response, "application/json");
    
    So yes you're right, you should have everything for a single result inside one double quote. A set of double quotes in your response is how you encapsulate data as a single result. The AutoComplete widget doesn't have any concept of columns, I was a bit confused as to why you kept referring to them. The reason the example data has comma seperated values is that that is the format for addresses. So the commas in "New Albany, IN, United States" are just part of the content for the result, they aren't an indication of separate columns of data. Likewise, you would probably separate the vehicle reg from the make with a comma but you could put the make in curved brackets or do any other kind of grammatical separation such as using a pipe or hyphen.

    It's working now, thank you SO MUCH for your kind help and patience with this Aswerty!!!

    One very last question with this, is it much hassle to make the Listview that comes back, selectable, as in each row returned by the Listview can be selected by the cursor, because that isn't the case at the moment as per the demo sample I originally implemented by JQM?


  • Registered Users Posts: 586 ✭✭✭Aswerty


    Well boards in a stunning display of incompetence has just wiped my reply while checking to make sure I'm not a robot. So I'll keep this reply short and sweet:

    You modify the following in the JavaScript to turn the list of results into links:
                        $.each(response, function (i, val) {
                            html += '<li><a href="#">" + val + "</li>';
                        });
    

    This will just create links to reload the current page, but it shows you how to make things selectable. You'd either need to return a more complex result that also contains information for the unique link for each result. Or you'd have to use the current results as parameters for a route (e.g. /vehicle?reg=06D1234). If going down the parameter route you'd have to look at how to deal with the result being both a reg and make.


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    Well boards in a stunning display of incompetence has just wiped my reply while checking to make sure I'm not a robot. So I'll keep this reply short and sweet:

    You modify the following in the JavaScript to turn the list of results into links:
                        $.each(response, function (i, val) {
                            html += '<li><a href="#">" + val + "</li>';
                        });
    
    This will just create links to reload the current page, but it shows you how to make things selectable. You'd either need to return a more complex result that also contains information for the unique link for each result. Or you'd have to use the current results as parameters for a route (e.g. /vehicle?reg=06D1234). If going down the parameter route you'd have to look at how to deal with the result being both a reg and make.

    This is so weird lol, this works and brings me back the list as before, 6 rows of data, 2 columns, but no links created, yippee...!

    [HTML]
    .then( function ( response ) {
    $.each( response, function ( i, val ) {
    html += "<li>" + val + "</li>";
    });
    [/HTML]

    When I modified the above to what you suggested:

    [HTML]
    $.each(response, function (i, val) {
    html += '<li><a href="#">" + val + "</li>';
    });
    [/HTML]

    I get back no data at all?!? They also look different on the intellisense screen colours which makes me think there may be a typo?!?

    408646.png

    + val + is in write text above but below it is in the orange colour which makes me think something isn't right?!?

    408647.png


  • Registered Users Posts: 586 ✭✭✭Aswerty


    A typo on my part,. I switched from " to ' so that I didn't need to escape the double quote. And I was missing the closing tag for the link. The following is correct.
                        $.each(response, function (i, val) {
                            html += '<li><a href="#">' + val + '</a></li>';
                        });
    

    The each function iterates through the results, so val is just a single result value on each iteration (e.g. 06D1234).


  • Closed Accounts Posts: 242 ✭✭Divelment


    Aswerty wrote: »
    A typo on my part,. I switched from " to ' so that I didn't need to escape the double quote. And I was missing the closing tag for the link. The following is correct.
                        $.each(response, function (i, val) {
                            html += '<li><a href="#">' + val + '</a></li>';
                        });
    
    The each function iterates through the results, so val is just a single result value on each iteration (e.g. 06D1234).

    Thanks so much Aswerty! Is it much hassle to get info out at the other end, as in passing the values of the data into a few labels when clicked?


Advertisement