How to have a custom value in JSON with JQueryi UI Autocomplete? - json

I'm using the JQuery UI autocomplete plugin (cached version) with JQuery-UI 1.11.1
Due to some server-side changes in the JSON I am using as source, I need to adapt my code.
Here is an example of my JSON:
[{
"name": "Varedo"
}, {
"name": "Varena"
}, {
"name": "Varenna"
}, {
"name": "Varese"
}]
produced by an URL with this style:
[url]/?name=vare
Since the GET variable is different from the default one ("term"), I already adapted my code for the custom request as suggested here:
$(function () {
var cache = {};
$("#searchTextField").autocomplete({
minLength: 3,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.getJSON("[url]", {
name: request.term
}, function (data, status, xhr) {
cache[term] = data;
response(data);
});
}
});
});
However I need to also adapt the code in order to use a custom JSON value (the default is "value" http://api.jqueryui.com/autocomplete/#option-source) which is in my case is "name" (as you can see from the JSON).
How can I do that?
At the moment this is what I get from the autocomplete:
So I guess I am somehow giving as response JS Objects and not strings.
Thanks in advance.

Currently you're saving the response as it is into your cache object, which is not valid format for jQuery UI autocomplete. You should convert the data into proper format digestable for autocomplete.
Either you should pass an array of strings, or an array of objects having label and value properties.
Since the response only contains name properties, you can convert it into an array of strings using jQuery map() method and save it in cache variable as follows:
$("#searchTextField").autocomplete({
minLength: 3,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.getJSON("[url]", {
name: request.term
}, function (data, status, xhr) {
cache[term] = $.map(data, function (obj) { // returns array of strings
return obj.name
});
// return the new array rather than original response
response(cache[term]);
});
}
});

Related

Kendo Grid Inline MultiSelect - Posted Values

I'm replicating the functionality very close to what's seen here. https://onabai.wordpress.com/2013/07/17/kendoui-multiselect-in-a-grid-yes-we-can/
I have Kendo grid with an inline multiselect editor field. I have a datasource.sync() event kicked off on change of that multiselect. The issue I'm having is how the data is arranged in the post variables.
I'm using FireBug in FireFox. I can set a function to view the values in my multiselect field like this at the sync() event.
console.log(this.value());
This would be for a string array field I have called "RoleCode". Anyway, the console log displays the values as they should, for example
A, OU
However, when I look in the Post call to my controller and at the parameters, I see the RoleCode field is duplicated, which is why my controller doesn't recognize the method signature. For example, this is what I see in FireBug...
ID 123
Field1 TextFromField1
RoleCode[1][RoleCode] OU
RoleCode[] A
Any idea how I should set this up so the post parameters are usable?
UPDATE
For now I just altered the update function to send the multiselect values as a comma separated string. I can deal with them in the controller. I don't really like this setup, but until I find how to get the posted values to send correctly, this is what I'm going with.
update: {
url: "Home/GridUpdate",
type: "POST",
dataType: "json",
data: function () {
//Grid does not post multiselect array correctly, need to convert to a string
var rolesString = $("#gridRoleList").data("kendoMultiSelect").value().toString();
return { rolesString: rolesString };
},
complete: function (e) {
setTimeout(function () {
refreshGrid();
}, 300);
},
success: function (result) {
// notify the data source that the request succeeded
options.success(result);
},
error: function (result) {
// notify the data source that the request failed
options.error(result);
}
},
UPDATE 2
Actually that's not a good idea because if I edit another field in the grid, I get a js error because the multiselect is not found.
Looks like your issue can be resolved by sending the data after serializing it
Read action - using MVC Wrapper
.Create(create => create.Action("Create", "Home").Data("serialize"))
JS Code
<script type="text/javascript">
function serialize(data) {
debugger;
for (var property in data) {
if ($.isArray(data[property])) {
serializeArray(property, data[property], data);
}
}
}
function serializeArray(prefix, array, result) {
for (var i = 0; i < array.length; i++) {
if ($.isPlainObject(array[i])) {
for (var property in array[i]) {
result[prefix + "[" + i + "]." + property] = array[i][property];
}
}
else {
result[prefix + "[" + i + "]"] = array[i];
}
}
}
</script>
Please refer here for complete source code
Here's how I solved it. On the change event of the editor function, I updated the value of the model with the value of the multiselect. Then the data posts correctly as a string array like this.
ID 123
Field1 TextFromField1
RoleCode[] A
RoleCode[] OU
My grid editor function
function roleMultiSelectEditor(container, options) {
$('<input id = "gridRoleList" name="' + options.field + '"/>')
.appendTo(container)
.kendoMultiSelect({
dataTextField: "RoleCode",
dataValueField: "RoleCode",
autoBind: true,
change: function (e) {
//Applies the value of the multiselect to the model.RoleCode field
//Necessary to correctly post values to controller
options.model.RoleCode = this.value();
processGridMultiSelectChange();
},
dataSource: {
type: "json",
transport: {
read: {
dataType: "json",
url: baseUrl + "api/DropDownData/RoleList",
},
}
},
dataBound: function (e) {
}
});
}

Select2 and JSON Data

I am using select2 version 4 and I have a REST service control on an XPage, that reads the fullname column from the names.nsf.
I have the search working, but for some reason, I don't get a list of values back I can select.
The JSON object being returned, looks something like this:
[{"#entryid":"1376-E6D5EBE8ADBEFA7088257DF8006E4BA2","fullname":"Full Name\/OU\/O"},{"#entryid":"1375-FD1CB92A13BFD0E088257DE4006756D7","fullname":"Another Full Name\/OU\/O"}]
The code to initialize the select2 looks like this:
x$( "#{id:comboBox1}" ).select2({
ajax: {
url: "xJSON.xsp/names",
dataType: 'json',
delay: 250,
data: function (params) {
return {
search:'[fullname=]*'+params.term+'*',
// q: params.term, // search term
page: params.page
};
},
results: function (data, page){
},
processResults: function (data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
console.log(data);
return {
results: data
};
},
cache: true
},
//escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1
});
When I look at the browser's console, I can see that the search worked and JSON objects are being returned, however, I don't get a list of values to select from.
For the result return I've tried results: data.fullname and results: data, text:'fullname' but nothing happens.
What am I doing worng?
You need to either switch your JSON response to include id and text for each object, or re-map them in your processResults method. These two properties are required on all selectable objects now in Select2 4.0. Since I'm assuming you either can't change your JSON response, or it wouldn't make sense to, you can easily re-map the data with the following processResults method.
processResults: function (data) {
var data = $.map(data, function (obj) {
obj.id = obj.id || obj["#entityid"];
obj.text = obj.text || obj.fullname;
return obj;
});
return {
results: data
};
});
This will map the #entityid property to the id property and the fullname property to the text property. So selections will be sent to your server containing the #entityid and will be displayed using the fullname.
Also, the results method is no longer needed in Select2 4.0. This was renamed to the current processResults method.
I copied your code exactly as it is, and just changed the fieldname and the search query and worked out just fine.
This is my JSON looks like
[{"#entryid":"1482-AD112B834158AD0D80257E4B004EC42E","#unid":"AD112B834158AD0D80257E4B004EC42E","id":"Victor Hunter","text":"Odhran Patton"},{"#entryid":"1496-291F2480D806A91E80257E4B004EC3D2","#unid":"291F2480D806A91E80257E4B004EC3D2","id":"Wesley O'Meara","text":"Wesley O'Meara"},{"#entryid":"1421-CC19D06880F5DC2980257E4B004EC537","#unid":"CC19D06880F5DC2980257E4B004EC537","id":"Stephen Woods","text":"Emma Doherty"}]
What I know is that select2 expects an id, and a text parameters from the JSON.

IBM Worklight JSONStore - Add and get data

I am using worlight JSONstore. I am new to it. I tried searching that read all docs but didn't get much idea.
I have one login page from that I get some json data I want to store that data using jsonstore. and get that afterwards.
I made jsonstore adapter.
Json-Store-Impl.js
function getJsonStores(custData) {
var data = custData;
return data;
//custdata is json
}
function addJsonStore(param1) {
var input = {
method : 'put',
returnedContentType : 'json',
path : 'userInputRequired'
};
return WL.Server.invokeHttp(input);
}
function updateJsonStore(param1) {
var input = {
method : 'post',
returnedContentType : 'json',
path : 'userInputRequired'
};
return WL.Server.invokeHttp(input);
}
function deleteJsonStore(param1) {
var input = {
method : 'delete',
returnedContentType : 'json',
path : 'userInputRequired'
};
return WL.Server.invokeHttp(input);
}
after that I Create a local JSON store.
famlCollection.js
;(function () {
WL.JSONStore.init({
faml : {
searchFields: {"response.mci.txnid":"string","response.mci.scrnseqnbr":"string","response.loginUser":"string","request.fldWebServerId":"string","response.fldRsaImageHeight":"string","request.fldRequestId":"string","request.fldTxnId":"string","response.fldDeviceTokenFSO":"string","response.fldRsaCollectionRequired":"string","response.datlastsuccesslogin":"string","response.fldRsaUserPhrase":"string","response.fldRsaAuthTxnId":"string","response.rc.returncode":"string","response.datcurrentlogin":"string","response.mci.deviceid":"string","response.customername":"string","request.fldDeviceId":"string","response.fldRsaUserStatus":"string","request.fldScrnSeqNbr":"string","response.fldRsaImageWidth":"string","request.fldLangId":"string","response.fldTptCustomer":"string","response.encflag":"string","response.rc.errorcode":"string","response.fldRsaImagePath":"string","response.mci.appid":"string","response.mci.requestid":"string","response.rc.errormessage":"string","response.mci.appserverid":"string","response.fldRsaCollectionType":"string","request.fldAppId":"string","response.fldRsaImageId":"string","request.fldLoginUserId":"string","response.mci.sessionid":"string","response.mci.langid":"string","response.mci.remoteaddress":"string","request.fldAppServerId":"string","response.mci.webserverid":"string","response.fldRsaImageText":"string","response.fldRsaEnrollRequired":"string","response.fldRsaActivityFlag":"string"},
adapter : {
name: 'JsonStore',
replace: 'updateJsonStore',
remove: 'deleteJsonStore',
add: 'addJsonStore',
load: {
procedure: 'getJsonStores',
params: [],
key: 'faml'
},
accept: function (data) {
return (data.status === 200);
}
}
}
}, {
password : 'PleaseChangeThisPassword'
})
.then(function () {
WL.Logger.debug(['Take a look at the JSONStore documentation and getting started module for more details and code samples.',
'At this point there is no data inside your collection ("faml"), but JSONStore is ready to be used.',
'You can use WL.JSONStore.get("faml").load() to load data from the adapter.',
'These are some common JSONStore methods: load, add, replace, remove, count, push, find, findById, findAll.',
'Most operations are asynchronous, wait until the last operation finished before calling the next one.',
'JSONStore is currently supported for production only in Android and iOS environments.',
'Search Fields are not dynamic, call WL.JSONStore.destroy() and then initialize the collection with the new fields.'].join('\n'));
})
.fail(function (errObj) {
WL.Logger.ctx({pretty: true}).debug(errObj);
});
}());
When I clicked on login button I call getJsonStores like this -
getJsonStores = function(){
custData = responseData();
var invocationData = {
adapter : "JsonStore",
procedure : "getJsonStores",
parameters : [custData],
compressResponse : true
};
//WL.Logger.debug('invoke msg '+invocationData, '');
WL.Client.invokeProcedure(invocationData, {
onSuccess : sucess,
onFailure : AdapterFail,
timeout: timeout
});
};
I followed these steps
Is this right way? and how can I check jsonstore working locally or not? and how can I store my jsondata in JSONStore? Where should I initialize the wlCommonInit function in project?
plz Help me out.
Open main.js and find the wlCommonInit function, add the JSONStore init code.
WL.JSONStore.init(...)
You already have an adapter that returns the data you want to add to JSONStore, call it any time after init has finished.
WL.Client.invokeProcedure(...)
Inside the onSuccess callback, a function that gets executed when you successfully get data from the adapter, start using the JSONStore API. One high level way to write the code would be, if the collection is empty (the count API returns 0), then add all documents to the collection.
WL.JSONStore.get(collectionName).count()
.then(function (countResult) {
if(countResult === 0) {
//collection is empty, add data
WL.JSONStore.get(collectionName).add([{name: 'carlos'}, {name: 'mike'}])
.then(function () {
//data stored succesfully
});
}
});
Instead of adding [{name: 'carlos'}, {name: 'mike'}] you probably want to add the data returned from the adapter.
Later in your application, you can use the find API to get data back:
WL.JSONStore.get(collectionName).findAll()
.then(function (findResults) {
//...
});
There is also a find API that takes queries (e.g. {name: 'carlos'}), look at the getting started module here and the documentation here.
It's worth mentioning that the JSONStore API is asynchronous, you must wait for the callbacks in order to perform the next operation.

create dijit accordian container from foreach loop with data returned from json

how do i use a for each loop to create accordian containers for each data returned from json file using ajax ?
i have tried this ! is it the way to it ?
dojo.xhrGet({
url:"json/"file_Name".json",
handleAs: "json",
timeout: 10000,
load: function(response,details){
container(response)},
error: function(error_msg,details){
container(error_msg, details);
}
});
//how do i use the json file to add data to the array arrFruit and then create dijit accordian container for every data in the array//
container = function(array, domConstruct) {
var arrFruit = ["apples", "kiwis", "pineapples"];
array.forEach(arrFruit, function(item, i){
domConstruct.create("li", {innerHTML: i+1+". "+item}, "properties");
});
};
//the response data from my json file is:-
[
{
"itemId": 1234,
"Name": "Name",
}]
I would suggest you re-write it into leveraging the ItemFileReadStore. The Store is a data container in which you can pull out items by their id. This means that your json needs to be changed slightly with description of what is identifier and - if any - which is the children attribute keys.
JSON:
{
identifier: 'itemId',
// you dont seem to have child references any but these are defaults
childrenAttrs: ['items', 'children'],
items: [
{
itemId: 1234,
name: 'Name'
}, {
...
}
]
}
then in your code, instead of using .xhr use .fetch in a store like so:
// 1.7+ syntax, pulling in dependencies.
// We want accordion and some other display widget like contentpane.
// Also we await domReady before calling our function
require(["dojo/data/ItemFileReadStore", "dijit/layout/AccordionContainer", "dijit/layout/ContentPane", "dojo/domReady!"], function(itemStore, accordion, contenpane) {
// this section is called when loading of itemstore dependencies are done
// create store
var store = new itemStore({
url:"json/"file_Name".json"
});
// create container
var acc = new accordion({style:"height: 300px"}, 'someDomNodeId');
// call XHR via .fetch and assign onComplete (opposed to 'load') callback
store.fetch({ onComplete: function(items) {
// items is an array of all the objects kept in jsonObject.items array
items.forEach(function(item) {
acc.addChild(new contentpane({
title: "Name for id: " + store.getValue(item, 'itemId'),
content: store.getValue(item, 'name')
}));
});
console.log(acc.getChildren()); // << would print out an array of contentpane widgets
});
});
This is howto :)
At any given time you could use the store and fetch some items, lets say you want to filter out some specific ones, call .query like so: store.fetch({query: { name: '*foo'/*all item.name ending with foo*/ }, onComplete: function(items) { /*cb func*/});
See
http://livedocs.dojotoolkit.org/dijit/layout/AccordionContainer#programmatic-example
and
http://livedocs.dojotoolkit.org/dojo/data/ItemFileReadStore

Retrieving search data from database using jQuery autocomplete?

I am using jQuery UI Autocomplete plugin for better data input in my ASP.NET web application.
http://jqueryui.com/demos/autocomplete/
However, I think I have somehow lost in this plugin.
I would like to ask what I should do in order to use this autocomplete function with the data retrieve from database?
I expect Ajax should be used for the real-time search,
but I have no idea how it can be done after looking at the demo in the website above.
Thanks so much.
Update:
Here is the code I have tried, doesn't work, but no error in firebug too.
$('#FirstName').autocomplete({
source: function (request, response) {
$.ajax({
url: "/Contact/FirstNameLookup?firstName=",
type: "POST",
data: {
"firstName": $('#FirstName').val()
},
success: function (data) {
response($.map(data, function (item) {
return {
label: item.FirstName,
value: item.FistName
}
}));
}
});
}
});
You need to create an action that does the lookup and returns the result as a JsonResult
e.g.
public ActionResult FirstNameLookup(string firstName)
{
var contacts = FindContacts(firstname);
return Json(contacts.ToArray(), JsonRequestBehavior.AllowGet);
}
I'm not sure if this will solve all your problems but here are a couple of edits you can make.
you don't need the "?firstname=" part of the url since you are using the data parameter for you ajax request.
rather than grabbing your search term with $('#FirstName').val(), try using the term property of the request object (request.term).
for example:
$('#FirstName').autocomplete({
source: function (request, response) {
$.ajax({
url: "/Contact/FirstNameLookup",
type: "POST",
data: {
"firstName": request.term
},
success: function (data) {
response($.map(data, function (item) {
return {
label: item.FirstName,
value: item.FistName
}
}));
}
});
}
});