1

I have the following script that is rendered inside my _layout view:-

$(document).ready(function () {
    $("input[data-autocomplete-source]").each(function () {
        var target = $(this);
        target.autocomplete({
            source: target.attr("data-autocomplete-source"), 
            minLength: 1, 
            delay: 1000
        });   
    });  
});

and i added the following field to apply autocomplete on it:-

<input  name="term" type="text" data-val="true" 
data-val-required= "Please enter a value."  
data-autocomplete-source= "@Url.Action("AutoComplete", "Staff")"  /> 

now if i render the view as partial view then the script will not fire, and no autocomplete will be performed, so i added the autocomplete inside ajax-success as follow:-

$(document).ready(function () {
    $(document).ajaxSuccess(function () {
        $("input[data-autocomplete-source]").each(function () {
            var target = $(this);
            target.autocomplete({
                source: target.attr("data-autocomplete-source"), 
                minLength: 1, 
                delay: 1000
            });
        });
    });
});

now after adding the AjaxSuccess the action method will be called, and when i check the response on IE F12 developers tools i can see that the browser will receive the json responce but nothing will be displayed inside the field (i mean the autocomplete results will not show on the partial view)?

EDIT

The action method which is responsible for the autocomplete is:-

public async Task<ActionResult> AutoComplete(string term)
      {


          var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term).Select(a => new { label = a.SamAccUserName }).ToListAsync();
          return Json(staff, JsonRequestBehavior.AllowGet);


      }

EDIT2

here is the script which is responsible to show the modal popup:-

$(document).ready(function () {

    $(function () {
        $.ajaxSetup({ cache: false });
        //$("a[data-modal]").on("click", function (e) {
            $(document).on('click', 'a[data-modal]', function (e){
            $('#myModalContent').css({ "max-height": screen.height * .82, "overflow-y": "auto" }).load(this.href, function () {
                $('#myModal').modal({
                    //height: 1000,
                    //width: 1200,
                    //resizable: true,
                    keyboard: true
                }, 'show');
                $('#myModalContent').removeData("validator");
                $('#myModalContent').removeData("unobtrusiveValidation");
                $.validator.unobtrusive.parse('#myModalContent');
                bindForm(this);
            });
            return false;
        });


    });

    function bindForm(dialog) {
        $('form', dialog).submit(function () {
            $('.btn.btn-primary,.btn.btn-danger').prop("disabled", "disabled");
            $('#progress').show();
            if ($(this).valid()) {

                $.ajax({
                    url: this.action,
                    type: this.method,
                    data: $(this).serialize(),
                    success: function (result) {
                       if (result.ISsuccess) {
                            $('#myModal').modal('hide');
                            $('#progress').hide();
                            $('.btn.btn-primary,.btn.btn-danger').prop("disabled", false);
                            location.reload();
                            //  alert('www');
                        } else {

                            $('#progress').hide();
                            $('#myModalContent').html(result);
                            $('.btn.btn-primary,.btn.btn-danger').prop("disabled", false);
                            bindForm();
                        }
                    }
                });
            }
            else {
                $('.btn.btn-primary,.btn.btn-danger').prop("disabled", false);
                $('#progress').hide();
                return false;
            }

            return false;
        });
    }
});
John John
  • 1
  • 72
  • 238
  • 501
  • can you show your `AutoComplete` controller method? – teo van kot Feb 10 '15 at 06:51
  • @teovankot i added the related action method – John John Feb 10 '15 at 11:37
  • i bet i find your problem, you can see answer update – teo van kot Feb 10 '15 at 12:08
  • Well after all updates, have you tried to put your autocomplete add code in `load` method? It's better to use `$.ajax` to get data, becouse `load` works a bit differently, but if you use `load`, add your autocomplete code in load `complete` [callback](http://api.jquery.com/load/) and see what's happened. – teo van kot Feb 10 '15 at 14:04
  • but sure if i get your point ??? where exactly i need to use load ? – John John Feb 10 '15 at 15:02
  • I suggest you to write your autocomplete init code right after `bindForm(this);` and see what's happened. – teo van kot Feb 10 '15 at 15:04
  • @teovankot i tried so but still the same problem. The action method will be called and the browser will receive the autocomplete results, but nothing will be displayed inside the field. i have noted something that the get request generated by the autocomplete inside the partial view will have two parameters ; the term and another parm _= such as ;- "/AutoComplete?term=t&_=1423587950831". but as i mentioned the action method is being called successfully and the browser will receive the json data.. i not sure but could the problem related that jquery-ui will not apply on partial views ? – John John Feb 10 '15 at 17:11
  • no, jquery ui and autocomplete can be used and works fine on partial Views. I only not shure, can it be related that `name` of `input` is `term`? – teo van kot Feb 11 '15 at 06:50
  • why term will cause any problem in this case ? again the autocomplete is working well if i render the view as regular view.. – John John Feb 11 '15 at 11:31
  • Sorry, my bad. I just can't reproduce problem... If you say, that json is getting back well, could it be css problem? – teo van kot Feb 11 '15 at 11:51
  • yes using F12 developer tool, i can see that the browser will receive the json ,, so the auto-complte is working well, but nothing is going to be displayed inside the autocomplete field.. – John John Feb 11 '15 at 13:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/70705/discussion-between-teo-van-kot-and-john-g). – teo van kot Feb 11 '15 at 13:08
  • Is your browser set to check for newer versions of pages? – Donal Feb 11 '15 at 15:40
  • @Donal no but how will this affect the problem. as i mentioned the auto-complete as a function is working well. since when i start typing inside the auto-complete field, the auto-complete action method will be called, and using the F12 developer tool i can see that the json response will be received by the browser,, but there is something preventing the returned json from being shown as autocomplete list .... – John John Feb 11 '15 at 15:45
  • @Donal one thing I need to mention is that when i start typing inside the autocomplete field i can see that the request will have two parameters as follow:- "/AutoComplete?term=t&_=1423587950831" so there is extra parameter "_=1423587950831" being sent,, but as i mentioned that action method will be called ... – John John Feb 11 '15 at 15:47
  • the response header is:-Cache-Control private, s-maxage=0 Content-Length 77 Content-Type application/json; charset=utf-8 Date Wed, 11 Feb 2015 15:54:22 GMT Server Microsoft-IIS/8.0 X-AspNet-Version 4.0.30319 X-AspNetMvc-Version 5.2 X-Powered-By ASP.NET X-SourceFiles =?UTF-8?B?QzpcVXNlcnNcQWRtaW5pc3RyYXRvclxEb2N1bWVudHNcVmlzdWFsIFN0dWRpbyAyMDEyXFByb2plY3RzXE5ldyBmb2xkZXJcU2tpbGxNYW5hZ2VtZW50VERNR3JvdXBcU2tpbGxNYW5hZ2VtZW50VERNR3JvdXBcQ3VzdG9tZXJcQXV0b0NvbXBsZXRl?= – John John Feb 11 '15 at 15:54
  • & the request header is :-Accept application/json, text/javascript, */*; q=0.01 Accept-Encoding gzip, deflate Accept-Language en-US,en;q=0.5 – John John Feb 11 '15 at 15:55
  • Cookie _RequestVerificationToken=6hXr9zHHh1tkuisAlh834pS9MGoYYTI33ltj_gZYh6CFNJGQ13hZrjin9T2Awpsfp_2HtacnMRLglcYggSDfOuL8W5fUGDd3HO8VQbsUTR01; ASPXAUTH=3601A06354322769E3F5B3AC21F41A8565B4B0485F2DD38BDDCD1464364965C86E20C83ADFA9C34FB24606BB4A9B1BA9A3EFAE57F5ABFA2523A2210C562131CB410EAEFD8E630E87B2D5BBAF22E2985F5A3FADE91D602A23BD1CF1B08C655E3BD87FC6166F77D55123E3E6A24783B1A6; T_SessionId=5uprfuxp5zhjaukzwj20ywig Host localhost:44304 Referer https://localhost:44304/Skill/Details/96 User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 X-Requested-With XMLHttpRequest – John John Feb 11 '15 at 15:55

1 Answers1

5

First, you don't need to wrap you ajaxSuccess fucntion in ready function.

Second, it's better to use POST when you get Json from server.

I tried to seproduce your problem, but have no luck.

Here how it works in my case(IE 11, MVC 4)

script on _Layout:

$(document).ajaxSuccess(function () {
    $("input[data-autocomplete-source]").each(function () {
        var target = $(this);
        target.autocomplete({
            source: function (request, response) {
                $.post(target.attr("data-autocomplete-source"), request, response);
            },
            minLength: 1,
            delay: 1000
        });
    });
});

Controller method:

[HttpPost]
public JsonResult AutoComplete()
{
    return Json(new List<string>()
        {
            "1",
            "2",
            "3"
        });
}

Partial View html:

<input name="term" type="text" data-val="true"
       data-val-required="Please enter a value."
       data-autocomplete-source="@Url.Action("AutoComplete", "Stuff")" />

UPDATE:

I find out what your problem is. Jquery autocomplete needs array of objects that have lable and value properties. So if you change your controller code like this and it will work.

public async Task<ActionResult> AutoComplete(string term)
{
    var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term)
    .Select(a => new { label = a.SamAccUserName, value = a.SamAccUserName })
    .ToListAsync();
    return Json(staff, JsonRequestBehavior.AllowGet);
}

Also you can do it on client side with $.map jquery function you can see example here

Community
  • 1
  • 1
teo van kot
  • 12,350
  • 10
  • 38
  • 70
  • thanks for the reply. now as i mentioned if i remove the script from ajaxSuccess , then the action method that is responsible for the autocomplete will never be called inside a partial view, while adding the scrip inside ajaxSuccess will call the action method that is responsible for the autocomplete and i will get the related json,, but the result will not show inside the browser. i test this on IE10, frefox, chrome – John John Feb 10 '15 at 11:37
  • one thing to mention is that i am loading the partial views inside modal popup using jQuery,, so maybe the autocomplete script can not understand newly added DOM ?? – John John Feb 10 '15 at 11:39
  • can you show how do you create jquery dialog and load View in it? Becouse i tested your example with `PartialView` within jQuery dialog and have no problem with autocomplete. – teo van kot Feb 10 '15 at 11:51
  • i added the value to the returned json but this did not solve the problem,, and i do not think this will cause any problem in all ways , because the autocomplete will work well if i render the view as non-partial view. now the script which will show the partial view as a modal pop-up is :- – John John Feb 10 '15 at 13:45
  • $(function () { $.ajaxSetup({ cache: false }); $(document).on('click', 'a[data-modal]', function (e){ $('#myModalContent').css({ "max-height": screen.height * .82, "overflow-y": "auto" }).load(this.href, function () { $('#myModal').modal({ keyboard: true }, 'show'); $('#myModalContent').removeData("validator"); $('#myModalContent').removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse('#myModalContent'); bindForm(this); }); return false; }); }); – John John Feb 10 '15 at 13:46
  • i have a feeling that the problem is that i am loading the autocomplete script when the page first load,,, then a partial view will be rendered,, so seems the script that is already loaded before the partial view renders will not be able to work on any newly added partial views... i am not sure if i can add an event delegation such as "$(document).on(....." so that script will stay Live()?? – John John Feb 10 '15 at 13:49
  • 1
    what `bindForm` function do? – teo van kot Feb 10 '15 at 13:53
  • i provided the full script inside my original question under :Edit2" section – John John Feb 10 '15 at 13:56
  • "Second, it's better to use POST when you get Json from server." this is totally wrong! The http methods ("get", "post", "put", "delete") to indicate the desire of an action. So if you want to get data, use get, if you want to create new data, put to modifie data an post to delete data. See http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods and http://en.wikipedia.org/wiki/Representational_state_transfer . – Stefan Feb 17 '15 at 00:50
  • @Stefan really don't understand what makes you so maad, that was not the problem of a question what HttpType to use, but not use GET is way better becouse of [JSON Hijacking](http://stackoverflow.com/a/8464685/1849444) and you talking about architecture recomendations, that you can keep if you want to build clean service. But you should agree with me, that if you need service, you will use MVC API Controller, and not usuall controller. – teo van kot Feb 17 '15 at 06:35
  • @tee-van-kot: sorry if I came over so wrong. I just did a lot of SPA rest devlopment and not being able to access the data via get makes it so much difficult to seen the data/debug. thanks for the great link, I don't know that and this is definitly a security vounablity. Please incude it in the answer, saying that you should either wrap the JSON into an object, or use post. – Stefan Feb 17 '15 at 14:17
  • @Stefan agree, but that is all for the sake of security. – teo van kot Feb 17 '15 at 14:18