Parsing JSON object in Jquery UI AutoComplete - c#

I have a feeling there is a simple answer to this, but I am having a problem when returning my JSON data to the JQuery UI Autocomplete function. I am using the 'label' and 'value' fields so I can store an id field. The problem is I am unable to parse the values in the object once they are passed back to the JQuery function.
in ASP.NET C#, I have an object:
public class AutoCompleteItem
{
public string label { get; set; }
public string value { get; set; }
}
and setting them into a list, formatting as JSON and then returning:
List<AutoCompleteItem> autoCompleteItems = new List<AutoCompleteItem>();
// Loop through data, add objects to list
var oSerializer = new JavaScriptSerializer();
string sJSON = oSerializer.Serialize(autoCompleteItems);
return sJSON;
JSON data after being passed to JQuery:
"[{"label":"Steve","value":"ID4545"},{"label":"Joe","value":"ID1212"},{"label":"Rick","value":"ID6767"}]"
and this is the function i am using to try and get the data from the JSON:
success: function (data) {
response($.map(data.d, function (item) {
return {
label: item.label,
value: item.value
}
}));
},
I noticed that before I used the 'label', 'value' format, I had it working with just an IList string. The data passed did not have quotes on the outside, whereas my original example does
["Steve", "Joe", "Rick"]
I don't know if this is related to the problem or not, but I have tried a number of things to no avail. Any help is appreciated!

There's no .d property in the JSON you have shown. So:
success: function (data) {
response(
$.map(data, function (item) {
return {
label: item.label,
value: item.value
};
})
);
},
But if you use an ASP.NET Page method then you have the .d property and you don't need to manually serialize the JSON. For example, you could have the following PageMethod in your code behind:
[WebMethod]
public static List<AutoCompleteItem> GetAutoCompleteValues(string term)
{
// the term variable will contain what the user entered so far
var autoCompleteItems = new List<AutoCompleteItem>();
// Loop through data, add objects to list
return autoCompleteItems;
}
and then:
source: function(request, response) {
$.ajax({
url: '/foo.aspx/GetAutoCompleteValues',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ term: request.term }),
success: function(data) {
response(
$.map(data.d, function(item) {
return {
label: item.label,
value: item.value
};
});
);
})
});
});

You shouldn't need to convert the JSON response - jQuery UI is already expecting those tokens.
From jQuery UI documentation:
$(function() {
function log( message ) {
$( "<div/>" ).text( message ).prependTo( "#log" );
$( "#log" ).scrollTop( 0 );
}
$( "#birds" ).autocomplete({
source: "search.php",
minLength: 2,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.value + " aka " + ui.item.id :
"Nothing selected, input was " + this.value );
}
});
});
You have direct access to the value and id properties of the item(s) as the second parameter jQuery passes to those event handlers (in the documentation example select:). No conversion should be required.

Why use JavaScriptSerializer() in the first place?
You only need
public ActionResult GetUserAutoComplete(string term)
{
var users = _userRepository.GetUsersByTerm(term);
var autoCompleteData = users.Select(x => new { label = x.Name + " " + x.Surname, value = x.Name + " " + x.Surname, id = x.UserId, }).ToArray();
return Json(data, JsonRequestBehavior.AllowGet);
}

Related

Get Object from KO.Observable

Sorry for the newbie question, I'm working with KnockoutJS and I am trying to get the base64String value from an observable and store it inside another observable before sending it off.
Why do I need to do that?
Well for some reason when the base64String is passed it has multiple layers to the object which get sent over as NULL.
Any help or suggestion will be appreciated.
var CreateSalesVM = {
UserId: ko.observable(),
Name: ko.observable(),
Phone: ko.observable(),
Email: ko.observable(),
Item: ko.observable(),
Description: ko.observable()
This piece is what I am having the issue with
IMAGETWO: ko.observable({
base64StringArray: ko.observableArray()
}),
IMAGE: ko.computed({
read: function () {
return IMAGETWO().base64StringArray();
},
deferEvaluation: true
}),
/**************\
btnCreateSales: function () {
// IMAGE = this.IMAGETWO().base64StringArray();
console.log("Image text ", this.IMAGE());
//console.log("Host usrl ", urlHostPath);
//console.log("Ko is ", ko.toJSON(this));
$.ajax({
url: urlPath,
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
//console.log("This was a success");
// window.location.href = urlPath + '/';
alert(ko.toJSON(this));
// console.log("Ko is ", ko.toJSON(this));
},
error: function (err) {
//console.log("Ko is ", ko.toJSON(this));
if (err.responseText == "success")
{
//console.log("This was an erro success", urlPath);
// window.location.href = urlPath + '';
}
else {
alert(err.responseText);
// console.log("This was an error ", urlHostPath );
}
},
complete: function () {
}
});
}
};
ko.applyBindings(CreateSalesVM);
IMAGETWO is a method of your VM object. You must specify the object while calling a function, otherwise it will look in a global scope for it. So, you may use either:
IMAGE: ko.computed({
read: function () {
return this.IMAGETWO().base64StringArray();
},
deferEvaluation: true
}, CreateSalesVM)
or
IMAGE: ko.computed({
read: function () {
return CreateSalesVM.IMAGETWO().base64StringArray();
},
deferEvaluation: true
})
This fails because you didn't specify on which object to call IMAGE (and by default it will be called on window).
In IMAGE, your view model does not exist yet because you are using object notation.
You need to change the way you define your view model, from object to class and add the object in IMAGETWO().base64StringArray(); as follows:
var CreateSalesVM = function () {
var self = this;
this.UserId = ko.observable();
this.Name = ko.observable();
this.Phone = ko.observable();
this.Email = ko.observable();
this.Item = ko.observable();
this.Description = ko.observable();
this.IMAGETWO = ko.observable({
base64StringArray: ko.observableArray()
});
this.IMAGE = ko.computed({
read: function () {
return self.IMAGETWO().base64StringArray();
//^^^^ note this
},
deferEvaluation: true
});
}
var myViewModel = new CreateSalesVM();
Whenever you call ko.toJSON(), you'll get a copy of your VM serialized as JSON. In this case that you need to post your object using ajax, all you have to do is override the toJSON() function to remove the IMAGETWO property and add IMAGE property with the transformation (to base 64) needed.
var CreateSalesVM = {
UserId: ko.observable(),
Name: ko.observable(),
Phone: ko.observable(),
Email: ko.observable(),
Item: ko.observable(),
Description: ko.observable(),
IMAGETWO: ko.observable({base64StringArray: ko.observableArray()})
}
CreateSalesVM.prototype.toJSON = function() {
var copy = ko.toJS(this); // clean copy
copy.IMAGE = this.IMAGETWO().base64StringArray(); // create desired property to send
delete copy.IMAGETWO; //remove the undesired property
return copy; //return the copy
};
Check-out the original post here.

mvc ajax refresh div method controller json

I have a method in the controller that return a ViewBag with Json.
public JsonResult FilterCheck(int id, int[] mycheck, string idprot)
{
ViewBag.Utenti = this.GetDbContext().utente.Include(s => s.cod_servizio_utente).Where(x => x.cod_servizio_utente.Select(l => l.id).Contains(5)).ToList();
return Json(ViewBag.Utenti, JsonRequestBehavior.AllowGet);
}
In the view I have this script function ajax, if this function have "success" i would refresh a div that include a foreach on the viebag.Utenti:
$.ajax({
type: "POST",
url: "#Url.Action("FilterCheck","Operatore")",
datatype: "json",
traditional: true,
data: { 'mycheck': mycheck, 'idprot': idprot, 'id': '#Model.id' },
success: function(data) {
var html = $(data).filter('#external-events').html();
$('#external-events').html(data);
}
});
<div id='external-events'>
#foreach (HAnnoZero.Repositories.utente item in ViewBag.Utenti)
{
<div class='col-lg-3'><div class='external-event'>#item.id- #item.cognome #item.nome</div></div>
} </div>
But dont work. How can do for refresh the foreach inside div id "external events"?Who could help me?
Firstly you do not need to assign the collection to ViewBag
public ActionResult FilterCheck(int id, int[] mycheck, string idprot)
{
var data = this.GetDbContext().utente.Include(......
// Build anonymous object collection to avoid circular reference errors
var response = data.Select(d => new
{
id = d.id,
cognome = d.cognome
// other properties as required
});
return Json(response);
}
Secondly you are returning JSON, not html, so in your success function you need to iterate through the properties and build your html (not sure what your properties are, so adjust as necessary)
success: function(data) {
$('#external-events').empty(); // clear existing items
$.each(data, function(index, item) {
var div = $('<div><div>'); // Create new element
div.text(item.id + ' ' + item.cognome); // Set inner text
$('#external-events').append(div); // add the new element
});
}
An alternative is to have the action method return a partial view containing the html and then use
success: function(data) {
$('#external-events').html(data);
}

How to retrive json result values in javascript?

I have a javascript function which redirects to given url after i had a json result.I want this json result values in my html inputs on success.Please help me i am new to MVC
function GetSupplierDetail(SupId) {
var url = "/PurchaseOrders/GetSupplierDetails/";
$.ajax({
url: url,
data: { SuppId: SupId },
cache: false,
type: "POST",
success: function (data) {
alert(data.modelList);
},
error: function (reponse) {
}
});
}
This is my C# Action.
[HttpPost]
public ActionResult GetSupplierDetails(int SuppId)
{ var books = entity.P_Supplier.Where(x => x.SupplierId == SuppId).ToList();
var modelList = books.Select(x => new SupplierModel()
{
Firm = x.Firm,
Sname = x.Sname,
SupplierName=x.SupplierName,
Address1=x.Address1,
Cell=x.Cell,
Email=x.Email,
Fax=x.Fax
});
return Json(modelList,JsonRequestBehavior.AllowGet);
alert(data.modelList); returns object which contains a collection.You need to loop over that collection.If you want to bind collection with GridView then there are different open source grids are available i.e Backgrid,flexigrid.
If there is just single result then you can check it by alert(data.modelList.Firm);
or assign it to any input fields.
$('#txtFirm').val(data.modelList.Firm);

KendoUI Cascading Dropdowns -- Retrieving json data from dropdown to use in controller

Oh boy what did I get myself into this time. Have to get some KendoUI cascading dropdrown lists working properly but I figure I will start off with two for now. Basically I need to retrieve whatever the user chooses for the first list in the view and send that back to the controller then pass it to an Entity Framework method (which I already have setup). Here is what I have now. The controller then passes back the appropriate 2nd dropdown list based on the first dropdown division value selected. I have tried using the Kendo stringify(data) trick in the parametermap as well as using cascadeFrom: "division", as suggested in the kendoui docs but that hasnt worked so far. Thus leading me to this interesting creation so far.
Any help or Garfield Comics are greatly appreciated.
The JS for the dropdownlists;
var divisions = $("#division").kendoDropDownList({
optionLabel: "Select category...",
dataTextField: "CodeAndDescription",
dataValueField: "Code",
dataSource: {
// type: "odata",
serverFiltering: true,
transport: {
read: {
url: VIPApiUrl + "GetDivision",
dataType: "json",
async: false,
type: "POST",
}, parameterMap: function (options, type) {
// edit VARS passed to service here!
if (type === 'read') {
return {
'division': options.division,
// 'criteria[0].Value': options.value
// ...
};
}
}
}
},
change: function () {
var value = this.value();
alert(value);
if (value) {
itemGroupDataSource.one("change", function () {
itemGroup.current(null);
}).filter({
field: "ID",
operator: "eq",
value: parseInt(value)
});
itemGroup.enable();
} else {
itemGroup.enable(false);
}
itemGroup.select(0);
}
}).data("kendoDropDownList");
var itemGroupDataSource = new kendo.data.DataSource({
//type: "odata",
serverFiltering: true,
transport: {
read: {
url: VIPApiUrl + "GetItemGroup",
dataType: "json",
async: false,
type: "POST",
}
}
});I
My controller where I need to access the json:
#region GetItemGroup
[HttpPost]
public List<ItemGroupsDTO> GetItemGroup(JObject jsonData)
{
dynamic json = jsonData;
string x = null; //intentionally pass null values
string division = json.division;
List<ItemGroupsDTO> ItemGroups = new List<ItemGroupsDTO>();
var ItemGroupEOList = new VIPItemGroupBOList();
ItemGroupEOList.Load(x, x, division, x, x, x, x, x, x, x, false);
foreach (var d in ItemGroupEOList)
{
var ItemGroup = new ItemGroupsDTO();
ItemGroup.Code = d.Code;
ItemGroups.Add(ItemGroup);
}
return ItemGroups;
}
#endregion
Okay I fixed this by changing the parameter map in the itemGroupDataSource to:
parameterMap: function (options, operation) {
return {
division: options.filter.filters[0].value
}
}
and changed the value field to:
dataValueField: "CodeAndDescription",
So I am guessing I partly wasn't giving the EO the right information but hopefully this helps someone in a Jam.

jquery-ui-autocomplete How can I set the ID into the textBox and it will return me the text value

I'm having a lot of trouble making jQuery's autocomplete widget work for me. I am using a list of key/value pairs from a server.
I have the following requirements:
If the user set the id of the value, like he knowes the code of the city
and instad of typing the name of a city he put the code of the city-- I want that the autocomplete will put the name of the city, and it dosn't!!
I edit My Code, now it works!
I add this lines
if (data.d.length == 1 && request.term.match(/\d+/g))
SetValue(textbox, hidden, data.d[0]);
else
and the function function SetValue(textbox, hidden, value){
textbox.focus().val(value.Text);
hidden.val(value.Semel);}
Another thing is if one is using the same page for creation and editting - on reloading the page while editting, you have to recreate all the spans etc for the values, and I want to send from the server just the code of the autocomplete, not the text value, and I want when i will set the value into the textBox, the autoComplete will start to work and will bring the value from the server
But with this I get still stuck:
I Dont know how to trigger the “autocomplete” event with send the value (the request value)
Here is My C# code:
[WebMethod(EnableSession = true)]
[ScriptMethod]
public List<IEntityBase> FetchList(string Text, string Code, string Dspl, int NumRecordes, string TableName)
{
Text = Server.UrlDecode(Text);
List<Tavla> tvListById = null;
int ignored = 0;
if (int.TryParse(Text, out ignored))
tvListById = TvList.GetTvListById(TableName, ignored, Code, Dspl);if (tvListById != null && tvListById.Count != 0)
return tvListById.Cast<IEntityBase>().ToList();
var fetchShem = TvList.GetData(TableName, Code, Dspl)
.Where(m => m.Shem.ToLower().Contains(Text.ToLower()))
.Take(NumRecordes);
return fetchShem.Cast<IEntityBase>().ToList();
}
and here is my Jquery Code:
enter code here
textbox.autocomplete({
source: function (request, response) {
$.ajax({
url: "AutoComplete.asmx/" + funcName,
data: "{ 'Text': '" + escape(request.term) + "','Code':'" + code + "','Dspl':'" + dspl + "','NumRecordes':'" + numrecordes + "','TableName':'" + tablename + "'}",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
if (data.d.length == 1 && request.term.match(/\d+/g))
SetValue(textbox, hidden, data.d[0]);
else
response($.map(data.d, function (item) {
return {
label: item.Text,
value: item.Semel
}
}));
}
},
error: function (msg) { alert(msg); }
});
},
minLength: minLength,
select: function (event, ui) {
var selectedObj = ui.item;
if (selectedObj) {
textbox.val(selectedObj.label);
hidden.val(selectedObj.value);
} return false; },
});function SetValue(textbox, hidden, value) {
textbox.focus().val(value.Text);
hidden.val(value.Semel);
}
For your first question, it all depends the logic you have tried , just in case if you have an id for any country then this shouldnt be any difficult.
Second query is all about performance of the page, this also shouldnt be any tougher if you try updating the elements based on the search pattern using ajax, where in you have to update just the realted elements,while keeping rest of your Page intact .
refer http://jquery.com/ for better understanding of the same

Categories