C# Webservice json data jquery ui with custom formatting - javascript

I'm using asp.net webservice to use it in jQuery UI autocomplete plugin and here is the data I'm getting.
{"d":[
{
"__type":"WebS.Model.SearchModel",
"MainCommodityId":1,
"MainCommodityName":"Pulses",
"SubcommodityId":3,
"SubCommodityName":"Urid Dal",
"BrandId":3,
"BrandName":"President"
},
{
"__type":"WebS.Model.SearchModel",
"MainCommodityId":1,
"MainCommodityName":"Pulses",
"SubcommodityId":1,
"SubCommodityName":"Red Gram",
"BrandId":4,
"BrandName":"President"
}
]
}
This is the script I'm using:
$(document).ready(function () {
$(".input-search").autocomplete({
source: function (request, response) {
$.ajax({
url: '/WebServices/GetAllBrandNames.asmx/getAllBrands',
data: "{ 'data': '" + request.term + "'}",
dataType: "json",
contentType: "application/json; charset=utf-8",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
return {
value: item.BrandName,
label: item.SubCommodityName
}
}))
},
error: function (response) {
alert('error');
},
failure: function (response) {
alert('faii');
}
});
},
select: function (e, i) {
console.log(i.MainCommodityId);
console.log(i.SubcommodityId);
console.log(i.BrandId);
},
minLength: 1
}).autocomplete("instance")._renderItem = function (ul, item) {
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>" + "" + item.BrandName + " in " + item.MainCommodityName + " - " + item.SubCommodityName + "</a>")
.appendTo(ul);
};
});
The issues are:
When I tried to enter keyword say: pre the aforesaid output is coming in json. However, the list is returning only one "President" item where it should display 2 items.
The list is displaying "undefined in undefined - undefined" instead of values after adding .autocomplete("instance")._renderItem function.
console.logs are also undefined after selecting an item.
How can these issues fixed?

The default behavior of the select event is to update the input with ui.item.value. This code runs after your event handler.
Simply prevent the default action on select and focus using event.preventDefault() or by return false and use _renderItem for custom dropdown.
focus: function(event, ui) {
// prevent autocomplete from updating the textbox
event.preventDefault(); // or return false;
}
select: function(event, ui) {
// prevent autocomplete from updating the textbox
event.preventDefault();
//do something
}
References:
jQuery UI Autocomplete Examples
Example 2

Finally, I was able to achieve what I wanted. Answering my question as it may helpful to someone.
javascript:
$(document).ready(function () {
$(".input-search").autocomplete({
source: function (request, response) {
$.ajax({
url: '/WebServices/GetAllBrandNames.asmx/getAllBrands',
data: "{ 'data': '" + request.term + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
// don't forget to $.map to (data.d where d is the top node
return {
// assign values from json response for further use
brandid: item.BrandId,
brand: item.BrandName,
maincommodityid: item.MainCommodityId,
maincommodity: item.MainCommodityName,
subcommodityid: item.SubcommodityId,
subcommodity: item.SubCommodityName
}
}));
},
error: function (response) {
alert('Server Error. Please try again.');
},
failure: function (response) {
alert('Failed to get result');
}
});
},
focus: function (event, ui) {
// prevent autocomplete from updating the textbox
event.preventDefault();
},
select: function (event, ui) {
// prevent autocomplete from updating the textbox
event.preventDefault();
// do further action here such as assigning id to hidden field etc.
$(".input-search").val(ui.item.brand);
// navigate to the selected item's url ex: /catalogue/1/1/pulses/red-gram/4/president
var str = "/catalogue/" + ui.item.maincommodityid + "/" +
ui.item.subcommodityid + "/" + $.trim(ui.item.maincommodity.replace(/\s+/g, '-').toLowerCase()) + "/" +
$.trim(ui.item.subcommodity.replace(/\s+/g, '-').toLowerCase()) + "/" + ui.item.brandid + "/" +
$.trim(ui.item.brand.replace(/\s+/g, '-').toLowerCase());
window.location = str;
},
minLength: 3
}).autocomplete("instance")._renderItem = function (ul, item) {
// get values and create custom display
var $a = $("<a></a>");
$("<strong></strong>").text(item.brand).appendTo($a);
$("<span></span>").text(" in ").appendTo($a);
$("<span></span>").text(item.subcommodity).appendTo($a);
return $("<li></li>").append($a).appendTo(ul);
};
});
CSS:
ul.ui-front {
z-index: 1200; // change z-index according to your UI.
}

Usually I do this way and Its work.
$(document).ready(function () {
var jsondata=array();
$.post("/WebServices/GetAllBrandNames.asmx/getAllBrands",{data: request.term},function(data){
var data=JSON.parse(data);
$.each(data.d, function( index, value ) {
jsondata[index].value=value;
});
$(".input-search").autocomplete({
source:jsondata,
//other property and events
})
});
I mean apply source JSON after completing request because sometimes if AJAX takes some time to load execution pointer still execute rest of code without waiting for response.
I did not test this code but I always do this way and never get your kind of error. Good Luck

Related

select2 returning position of items, not ID of items

I'm using a select2 to allow the user to select multiple options. Everything is working fine, except for one frustrating issue.
The first time I click the save button to save the items, it works. But then on subsequent calls, the ID of the items are replaced with the position of the items. For for example, if I have IDs 3, 6 and 10 selected, the first Save will work and 3,6,10 are passed to the controller.
But then if I reload the view and click save, the numbers 0,1,2 are passed in (ie, their relative positions in the select).
Here is the code:
Firstly, the HTML:
<select id="selectGroup" class="form-control" multiple="true">
On $(document).ready:
// Load Groups
$("#selectGroup").select2({ placeholder: 'Select' });
$.ajax({
url: ROOT_URL + "Group/GroupList",
type: "GET",
success: function (data) {
let dropdown = $('#selectGroup');
dropdown.empty();
dropdown.append($('<option></option>').attr('value', 0).text("(Select)"));
$.each(JSON.parse(data), function (key, entry) {
dropdown.append($('<option></option>').attr('value', entry.GroupID).text(entry.GroupName));
})
},
error: function (passParams) {
Notify(passParams, "Unexpected Error Loading Groups", "error");
}
});
And finally the js for the save (called from a button which passes in the loanID):
function LoanGroupSave(loanID) {
var grpIDs = '';
[].forEach.call(document.querySelectorAll('#selectGroup :checked'), function (elm) {
grpIDs += elm.value + ',';
})
var editURL = location.protocol + '//' + location.host + "/Loan/LoanGroupSave";
//alert(editURL);
var obj = { "LoanID": loanID, "GroupIDs": grpIDs };
alert(JSON.stringify(obj));
$.ajax({
type: "POST",
url: editURL,
data: JSON.stringify(obj),
contentType: "application/json; charset=utf-8",
dataType: "json",
}).done(function (response) {
if (response.success) {
Notify("Group(s) information has been saved", "Saved", "success", false, "toast-top-right", 5000);
}
else {
OpenPopupGeneral("Error(s)", response.message);
}
}).fail(function (jqXHR, textStatus, errorThrown) {
OpenPopupGeneral("Unexpected Error(s)", "Error = " + errorThrown);
});
}
Posting for people who make the same mistake.
Problem was in my load - I needed to add the GroupID as the key, not the row number which was in the key parameter value:
success: function (data) {
$.each(JSON.parse(data), function (key, entry) {
var $newOption = $("<option selected='selected'></option>").val(entry.GroupID).text(entry.GroupName);
$("#selectGroup").append($newOption).trigger('change');
}

Asp .net ajax autocomplete not working. Webmethod is not getting called

Can somebody tell me why WebMethod is not firing in one page alone, this same code works in another page, but not in the page which i want it to work. I shifted this entire code into a new page and it works perfectly fine there, but if i use it in my actual page, it doesn't fire the webmethod. Not sure what's happening.
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.10.0.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.9.2/jquery-ui.min.js" type="text/javascript"></script>
<link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.9.2/themes/blitzer/jquery-ui.css" rel="Stylesheet" type="text/css" />
<script type="text/javascript">
$(function () {
$("[id$=txtSkill]").autocomplete({
source: function (request, response) {
$.ajax({
url: '<% =ResolveUrl("HRMCareerEAF.aspx/GetSkills") %>',
data: "{ 'prefix': '" + request.term + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.split('-')[0],
val: item.split('-')[1]
}
}))
},
error: function (response) {
alert(response.responseText);
},
failure: function (response) {
alert(response.responseText);
}
});
},
select: function (e, i) {
$("[id$=hfSkillID]").val(i.item.val);
},
minLength: 1
});
});
</script>
<asp:TextBox ID="txtSkill" runat="server" style="text-align: center" />
[WebMethod(EnableSession = true)]
public static string[] GetSkills(string prefix)
{
HRMRecruitmentProcessDAL obj = new HRMRecruitmentProcessDAL();
DataSet ds = obj.BindMstcommon(HttpContext.Current.Session["CandidateID"].ToString(), "GetSkillsDD", "%" + prefix + "%");
List<string> skills = new List<string>();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
skills.Add(string.Format("{0}-{1}", ds.Tables[0].Rows[i]["Skill_Desc"].ToString(), ds.Tables[0].Rows[i]["skill_id"].ToString() + "|" + ds.Tables[0].Rows[i]["Skill_GroupID"].ToString())); //ds.Tables[0].Rows[i]["Skill_GroupDesc"].ToString() + " : " +
}
return skills.ToArray();
}
Can you please check few things
1) check if you are able to call the api using rest api testing tools like postman
2) If you are able to access it can you please check if web developer tool console if it has any error like 404(Not found) or 500(Internal server error)
3) Modify your
data: "{ 'prefix': '" + request.term + "'}",
to
data: JSON.stringify({ prefix: request.term }),
Please check value of '<% =ResolveUrl("HRMCareerEAF.aspx/GetSkills") %>'
Also I am not sure but try getting rid of (EnableSession = true).
Thank you soo much for the support.
I found out the problem and solution.
Actual problem is that auto complete doesn't work after partial page postback and my txtskill is in 3rd view of asp:multiview which refreshes only the part of page inside my updatepanel.
Jquery methods do not bind if the page postbacks partially. I got solution in the following link.
Jquery Auto complete extender not working after postback
My altered code is as follows.
<script type="text/javascript">
$(function () {
SetAutoComplete();
});
$(document).ready(function () {
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
// Place here the first init of the autocomplete
SetAutoComplete();
});
function InitializeRequest(sender, args) {
}
function EndRequest(sender, args) {
// after update occur on UpdatePanel re-init the Autocomplete
SetAutoComplete();
}
function SetAutoComplete() {
$("[id$=txtSkill]").autocomplete({
source: function (request, response) {
$.ajax({
url: '<% =ResolveUrl("HRMCareerEAF.aspx/GetSkills") %>',
data: JSON.stringify({ prefix: request.term }),
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.split('-')[0],
val: item.split('-')[1]
};
}))
}
});
},
select: function (e, i) {
$("[id$=hfSkillID]").val(i.item.val);
},
minLength: 1
});
}
</script>
Thank yo soo much for the support.

Error: object doesn't support 'autocomplete'

I have this function using the jquery autocomplete widget, that I am getting the following error:0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'autocomplete'
On my html page, in the head section I have included the following tags.
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script src="Scripts/jquery-ui-1.11.4.min.js"></script>
The function is called by a variety of option button calls to do several different query's. I have this function in a different application that works well but here it is not.
function AutoComplete(Type) {
//create AutoComplete UI component
$("#txtCriteria").autocomplete({
source: function (request, response) {
$.ajax({
autoFocus: true,
async: false,
delay: 250,
url: "wsReports.asmx/AutoComplete",
data: "{'Type':'" + Type + "', 'filter':'" + request.term + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.ACName,
value: item.ACCode
} // end of return
})) // end of response
} // end of success
}); // end of ajax
}, // end of source
select: function (event, ui) {
if (ui.item.value == "") {
alert("nothing to select");
}
else {
// prevent autocomplete from updating the textbox
event.preventDefault();
// manually update the textbox and hidden field
$(this).val(ui.item.label);
}
}, // end of select
change: function (event, ui) {
if (!ui.item) {
$(event.target).val('');
}
},
}) // end of txtCriteria.autocomplete
} // end of AutoComplete
Any ideas why it is not recognized in the above situation?
My fault. The jquery.js and bootstrap were loading after the jquery-ui.

Want to prevent selecting specific item in jQuery UI AutoComplete

I am developing textbox with autocomplete using jQuery UI Autocomplete.
After that, I can create textbox with autocomplete, but one issuce has occured now.
In my textbox, I want to prevent selecting specific item from autocomplete list.
If I select specific item, Autocomplete list display again or not to close.
$(function (prefixText) {
$("textBox").autocomplete({
autoFocus: false,
minLength: 0,
delay: 50,
source: function (request, response) {
var data = "{ 'prefixText': '" + prefixText
+ "','count': '" + 30
+ "','pixWidth': '" + 100 + "' }";
$.ajax({
type: "POST",
url: "Example.asmx/" + method,
cache: false,
data: data,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.name,
id: item.id,
name: item.name
}
}))
}
});
},
select: function (event, ui) {
var id = ui.item.id
//not match guid type
if (id.match(/[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}/) === null) {
if ($("text_id") !== null) {
$("text_id").val(-1);
}
return false
}
else {
if ($("text_id") !== null) {
$("text_id").val(ui.item.id);
}
$("textBox").val(ui.item.name);
}
}
});
});
});
If someone know answer, please teach me.
Based on the example from here: How to disable element in jQuery autocomplete list
I think this code will work for you:
$(function (prefixText) {
$("textBox").autocomplete({
autoFocus: false,
minLength: 0,
delay: 50,
source: function (request, response) {
var data = "{ 'prefixText': '" + prefixText
+ "','count': '" + 30
+ "','pixWidth': '" + 100 + "' }";
$.ajax({
type: "POST",
url: "Example.asmx/" + method,
cache: false,
data: data,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.name,
id: item.id,
name: item.name
}
}))
}
});
},
select: function (event, ui) {
var id = ui.item.id
//not match guid type
if (id.match(/[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}/) === null) {
if ($("text_id") !== null) {
$("text_id").val(-1);
}
return false
}
else {
if ($("text_id") !== null) {
$("text_id").val(ui.item.id);
}
$("textBox").val(ui.item.name);
}
}
}).data("ui-autocomplete")._renderItem = function (ul, item) {
//Add the .ui-state-disabled class and don't wrap in <a> if value is empty
var id = item.id
if (id.match(/[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}/) === null) {
return $('<li class="ui-state-disabled">'+item.label+'</li>').appendTo(ul);
} else{
return $("<li>")
.append("<a>" + item.label + "</a>")
.appendTo(ul);
}
};
});
If you can provide a working version of your code (the items can also be from a predefined list, not based on ajax call) it will be much easier to help.

Alter the filter on autocomplete to allow sorting on complete string

I have a functioning autocomplete jQuery input control but there are two things it is doing that I would like to alter.
First, it fires again and again. I would like for the data to be returned once, cached and not called again.
Second, I would like for the user to type in the control and based on what they type be able to search the entire string and not just the beginning.
This is my functioning script that returns data to the autocomplete and WORKS.
<script type="text/javascript">
$(function () {
$('#datePicker').datepicker();
});
$(document).ready(function() {
$("#autocomplete").autocomplete({
source: function (request, response) {
$.ajax({
url: "FacilitiesAsync",
type: 'GET',
cache: true,
data: 'sourceDb=myDb',
dataType: 'json',
success: function (json) {
// call autocomplete callback method with results
response($.map(json, function (name) {
return {
label: name.label,
value: name.value
};
}));
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
$("#autocomplete").text(textStatus + ', ' + errorThrown);
}
});
},
select: function (event, ui) {
$('#autocomplete').val(ui.item.label);
return false;
},
messages: {
noResults: '',
results: function () {
}
}
});
});
</script>
I found this bit of code that overrides the filter feature of the autocomplete but I have NO IDEA where to add this. I have tried several places to no avail....
// Overrides the default autocomplete filter function to search only from the beginning of the string
$("#autocomplete").autocomplete.filter = function (array, term) {
var matcher = new RegExp("\\b" + $.ui.autocomplete.escapeRegex(term), "i");
return $.grep(array, function (value) {
return matcher.test(value.label || value.value || value);
});
};
My input control looks like this.
<input id="autocomplete" />
I appreciate the direction...
To cache the data from your server, setup a separate function which handles (and caches, if necessary) the response from your ajax call:
var cachedResult = null;
function fetchResponse(callback) {
if (cachedResult) callback(cachedResult)
$.ajax({
url: "FacilitiesAsync",
type: 'GET',
cache: true,
data: 'sourceDb=myDb',
dataType: 'json',
success: function (json) {
// call autocomplete callback method with results
var cachedResult = $.map(json, function (name) {
return {
label: name.label,
value: name.value
};
});
callback(cachedResult);
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
$("#autocomplete").text(textStatus + ', ' + errorThrown);
}
});
}
$(document).ready(function() {
$("#autocomplete").autocomplete({
source: function (request, response) {
fetchResponse(function(result) {
response(result)
})
}
});
});
As for the custom matcher, look no further than the docs, in the Using a custom source callback to match only the beginning of terms example. Your custom matcher only differs in the regex pattern. Note also that this is all done within the "source" callback.

Categories

Resources