Issue with JSON parsing - javascript

I am a complete noob with JSON parsing in jQuery. Thought I got the response... My data is in this form:
Array(
[1]=>abc,
[3]=>mango,
[4]=>apple,
[5]=>fruits
)
In this way I want this list to appear as an autocomplete list. I am using.
jQuery("#name").autocomplete( '<?php echo HTTP_PATH.'/songs/sss'; ?>', {
multiple: true,
mustMatch: true,
matchContains: true,
autoFill: false,
dataType: "json",
parse: function(data) {
return jQuery.map(data, function(item) {
return { data: item, value: item.label, result: item.label};
});
},
formatItem: function(item) {
return item.label;
},
formatResult: function(item) {
return item.id;
},
formatMatch: function(item) {
return item.label;
}
});
I want the value when it shows list, i.e. the label from my data. When I select a label then it should show the label. But at the time of submission it should actually submit the key.
I mean I want it to work as select box of HTML.
Returned JSON
[{"id":1,"label":"Mehdi Hassan"},{"id":2,"label":"Jagjit Singh"},{"id":3,"label":"Suresh Vadekar"}]

Your JSON seems to not be an array, just an object (hash map).
Check out official docs:
Expected data format
The data from local data, a url or a callback can come in two
variants:
An Array of Strings: [ "Choice1", "Choice2" ]
An Array of Objects with label and value properties: [ { label: "Choice1", value: "value1" },
... ]
In your case it should be in the following format:
[
{"1":"Shad.aab"},
{"158":"Adadad"},
{"159":"Asdadad"},
{"166":"Abbas"},
{"167":"Sdadad"},
{"171":"Shadaab Please check it out"},
{"173":"Check This Please"},
]
(Remember that left side is label, right value, I suppose in your data, all should be reversed...)

If I understand you correctly, you want to use autocomplete to populate a name textfield, but want to leverage another value associated w/ the name in the form POST.
[If you're able to use latest jQueryUI version of autocomplete] - Following the "Custom Data and Display" autocomplete example at http://jqueryui.com/demos/autocomplete/#custom-data, you'll see that on autocomplete hint, they display the selected label, however, they also save an associated value in a hidden input that is also posted back to server. Given your current json format:
html:
<label for="username">Name:</label>
<input id="username" size="50" /> <!-- holds display name -->
<input id="userid" name="userid" size="50" /> <!-- holds userid -->
...
js:
<script>
$("#username").autocomplete({
source: '<?php echo HTTP_PATH.'/songs/sss'; ?>',
// Update display name when user mouses over selection
focus: function( event, ui ) {
$( "#username" ).val( ui.item.label );
return false;
},
// Set display name and hidden input on user selection
select: function( event, ui ) {
$( "#username" ).val( ui.item.label );
$( "#userid" ).val( ui.item.id );
return false;
}
});
</script>
php POST target:
<?php
// Use [hidden] input to do your magic
if(isset($_POST['userid']))
echo 'Wooo..here is my key: ' . $_POST['userid'];
?>

The problem looks like it's here:
jQuery("#name").autocomplete( '<?php echo HTTP_PATH.'/songs/sss'; ?>', { multiple: true, ...
It should be like this:
jQuery("#name").autocomplete( { source: '<?php echo HTTP_PATH.'/songs/sss'; ?>', multiple: true, ...
Also make sure you are using it on load/ready and not just inside a plain <script> tag
$(function(){ jQuery("#name").autocomplete(); });
Use firebug to verify that when you type a letter in that field it sends a request to the source page set for autocomplete.
Here is the code I used to re-create/fix your problem:
index.php
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/ui-lightness/jquery-ui-1.8.20.custom.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.20.custom.min.js"></script>
<script type="text/javascript">
$(function(){
jQuery("#name").autocomplete({
source: 'index_json.php',
multiple: true,
mustMatch: true,
matchContains: true,
autoFill: false,
dataType: "json",
parse: function(data) {
return jQuery.map(data, function(item) {
return { data: item, value: item.label, result: item.label};
});
},
formatItem: function(item) {
return item.label;
},
formatResult: function(item) {
return item.id;
},
formatMatch: function(item) {
return item.label;
}
});
});
</script>
</head>
<body>
<form>
<label for="name">Name: </label>
<input id="name" name="name" />
</form>
</body>
</html>
index_json.php
<?
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Content-type: application/json');
echo '[{"id":1,"label":"Mehdi Hassan"},{"id":2,"label":"Jagjit Singh"},{"id":3,"label":"Suresh Vadekar"}]';
?>
I am very confused with your request, but have taken your code and made it work how you specified (I think).
I want value when it show list.i.e. Label from my data. When I select label than also it should show label. but at time of submission it should actually submit key. I mean i want it to work as select box of HTML.
It almost sounds as if you want an input box for just searching and a static select list that changes from autocomplete but stays there instead of disappearing...

You need to do json_encode($your_array) in backend.
It will convert PHP Array into your JSON encoded strings that your front-end (jQuery) can then parse and process.

I am not sure I understood your question well. But I faced the same kind of requirement in my experience. I used ajax autocomplete js from the above link. (Go thru the link for complete details)
The highlight here is, this js provides you a callback onSelect with which you can set your values after selection of the auto complete suggestion.
The json encoded string should be like
query:'Li',
suggestions:['Mahendi Hassan','Libyan Arab Jamahiriya','Liechtenstein','Lithuania'],
data:['1','2','3','4']
query - original query value
suggestions - comma separated array of suggested values
data (optional) - data array, that contains values for callback function when data is selected.
Now have some hidden input field in your form, and set the selected suggestion's data to value of that hidden input field like this.
jQuery(function () {
options = {
minChars: 2,
serviceUrl: "ur/php file",
onSelect: function (value, data) {
$('#hiddenUserProfileIdProps').val(data); //Setting value to hidden field
}
});
a = $('#enterEmailLink').autocomplete(options);
a.disable();
});
Then submit your form. Thats it.

Related

Kendo AutoComplete Default Value

Need Value Already Set
I am using Kendo autocomplete to select an item from a list. I need to set the value of the text input field and make that actually use the value from the list.
Right now I am setting the text value of the input field to the value of the item in the table, though it is not actually using it as though you were to type it in and click on the auto-completed item.
Setting the default text :
IQueryable<StorageLocation> query = (from s in db.StorageLocations.Include("StorageLocationType") select s);
DefaultStorageLocation = query.Count() != 1 ? "" : query.FirstOrDefault().TitleWithType;
Setting the value of the text box:
<input type="text" value="<%: Model.DefaultStorageLocation %>" name="StorageLocation" id="StorageLocation" originalname="StorageLocation" placeholder="" class="autoComplete" style="width: 158px;" />
My Kendo AutoComplete:
$('#StorageLocation' + rowID).kendoAutoComplete({
dataTextField: 'title',
dataValueField: 'id',
minLength: 2,
autoBind: false,
select: function (e) {
var dataItem = this.dataItem(e.item.index());
$('#StorageLocationID' + rowID).val(dataItem.id);
},
dataSource: {
type: 'json',
serverFiltering: true,
transport: {
read: {
url: function (opt) {
return '/Autocomplete/StorageLocations?searchText=' + opt.filter.filters[0].value;
}
}
}
}
});
So in short.
I am setting the value of the text input
Need it to actually use the value as if it were selected from autocomplete
It looks like you're trying to auto-select the first value when there is only one. I think the suggest property will do what you're looking for: http://docs.telerik.com/kendo-ui/api/javascript/ui/autocomplete#configuration-suggest
Alternatively, try the value method: http://docs.telerik.com/kendo-ui/api/javascript/ui/autocomplete#methods-value
Controller searchResult search query
storageLocation = (DefaultWarehouseForIA && !StorageLocation.IsNull()) ? StorageLocation.TitleWithType : "",
defaultStorageLocationID = (DefaultWarehouseForIA && DefaultStorageLocationID.ToLong() > 0) ? DefaultStorageLocationID : null
JS values being filled when another text field is filled in.
select: function (e) {
var dataItem = this.dataItem(e.item.index());
$('#StorageLocation' + rowID).val(dataItem.storageLocation);
$('#StorageLocationID' + rowID).val(dataItem.defaultStorageLocationID);
}
At this point I have figured it out. Have it working.
So now the value is being auto filled when another text field is being filled in.
Explanation isn't too great here. But hey.

Selecting an autocomplete list does not save the word fully when using ajax to save

I built an autocomplete list of cities using a mysql query. Typing in the input field correctly initiates the search and builds the selectable city list. The problem is that the city name in full does not get saved, only the characters typed when using .on('change'... I tried other mouse events such as mouseover, mousemove, mouseout, mouseenter, mouseleave - and they require the user to first select the item from the list, move out, then swipe the cursor over the input a second time to actually trigger the save of the selected city name. The html looks like:
<input type="text" onmouseover="this.focus();" class="saveCity" name="pob_city" member_id="<?php echo $member_id; ?>" value="<?php echo $pob_city; ?>" placeholder="City" id="pob_city" />
<script language="javascript" type="text/javascript"> $("#pob_city").coolautosuggest({ url:"tools/autosuggest/query_cities.php?chars=" }); </script>
The saveCityCountry javascript:
$(document).on('mouseout','.saveCity',function()
{
var DATA=$(this).val();
var n =remove_whitespaces(DATA);
var MEMBER_ID=$(this).attr('member_id');
$("#Results").html( "" );
if(n !=''){
var dataString = 'pob_city='+ n +'&member_id='+MEMBER_ID;
$.ajax({
type: "POST",
url: "saveData.php",
data: dataString,
cache: false,
success: function(html)
{
$("#Results").html( html );
}
});
}
})
You can see a demo at: http://dottedi.us/misc/ajaxsave/
The other thing that is slightly bothersome is that with ordinary input fields such as first or last name, the on change event only triggers when you click somewhere else on the page, thus the placebo "Save" button.
Update: I cleaned up the code in my example splitting off City from Country and updated the post to reference saveCity. This will not affect the result, just a bit easier to follow.
Inside the http://dottedi.us/misc/ajaxsave/tools/autosuggest/js/ folder are two javascript files that might be relevant, jquery.coolautosuggest.js and jquery.coolfieldset.js. On line 46 of jquery.coolautosuggest.js I see success:function(data){. You want me to place "source: data, autoFocus: true, delay: 0, minLength: 0, select: response, response: response" somewhere in here? Please make it clear where and with the right syntax, semicolin, etc.
In the codeblock you added, I assume that I change the HTML adding the ,response and the function response just gets placed somewhere within my saveData.js. Once this is right, do I go back to change as opposed to mouseout or mouseover?
include response function in your autocomplete call, where you can assign the selected value to hidden field, This will allow you to retain full text.
I assume you are getting array of cities, store each city in an array in a key called "city" and return it.
Define one hidden field say "selected_city".
Inside your coolautosuggest success function place this code
source: data,
autoFocus: true,
delay: 0,
minLength: 0,
select: response,
response: response
$("#pob_city").coolautosuggest({ url:"tools/autosuggest/query_cities.php?chars=" },response);
function response(){
if (typeof ui.content != "undefined" && ui.content.length === 1) {
city= ui.content[0].city;
}
else if (typeof ui.item != "undefined" && ui.item.label.length > 0) {
city= ui.item.label;
}
if (label.length > 0 || index.length > 0) {
$("#selected_city").val(city);
// this value you can use to display
}
}
before doing this please change the below function on jquery.coolautosuggest.js at line 120
if(me.submitOnSelect==true){ $("form").has(me.textField).submit();
}
to
if(me.submitOnSelect==true){
$("#pob_city").val($(this).find(".suggestion_title").text()); $("form").has(me.textField).submit();
}

Select2 AJAX selected value is not appearing int he box

Select2 - Version 4.0.0-beta.3
I am working to upgrade my Select2 from 3 to 4.0. I am having issue processing the ajax request with Select2.
I have following field.
HTML
<input action="load_users" id="id_pic_credits" name="pic_credits" type="hidden">
JS
$(document).ready(function () {
$("*[action='load_users']").select2({
allowClear: true,
width: '100%',
multiple: false,
minimumInputLength: 1,
"ajax": {
"url": _url,
delay: 250,
dataType: "json",
data: function (search, page) {
return search
},
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
return {
results: data.items
};
},
cache: true
}
});
});
HTML Result
Server Response
List of dicts.
[{'id':1, 'text':'Ray of Peace'},{'id':2, 'text':'Ray of Peace2'}]
HTML Result
Problem
When i click on any of the records; I can not see if the value is actually is getting select.
When the drop down closes; i do not see the selected value.
The value of the field is changed in the HTML though; but I can not see the result.
It is my understanding that you are no longer supposed to use a hidden input element to back your Select2 control. Instead, you should always use a <select> element.
Change your html to:
<select action="load_users" id="id_pic_credits" name="pic_credits"></select>
See the "No more hidden input tags" section on the Select2 4.0 Announcement page.
jsfiddle

Javascript populates input, but not span?

I am using Select2 dropdown menu to get data from database threw ajax and json/php.
The option i make will then populate some input fileds for editing the database.
I use (This field get´s populated ok):
<input type="text" class="form-control" name="valt_element_id" id="valt_element_id" placeholder="Objekt ID" />
But on some field i just want to show the data, not to be edited.
I figured to use:
<span id="valt_element_id"></span>
But this span code won´t work!
Why?
JS:
$(document).ready(function(){
var valtObjektElement = $('#valj_objekt_element');
$('#valj_objekt_element').select2({
ajax: {
url: "valj_objekt_element.php",
dataType: 'json',
data: function (term, page) {
return {
q: term
};
},
results: function (data, page) {
return { results: data };
}
} // Ajax Call
}); // Select2
// Start Change
$(valtObjektElement).change(function() {
var ElementId = $(valtObjektElement).select2('data').id;
var ObjektNummer = $(valtObjektElement).select2('data').text;
$('#valt_element_id').val(ElementId);
$('#valt_objekt_nummer').val(ObjektNummer);
}); //Change
}); //Domument Ready
There is no value attribute for span. You should either use text or html.
Replace
$('#valt_element_id').val(ElementId);
with
$('#valt_element_id').text(ElementId);
Using javascript:
document.getElementById("valt_element_id").innerHTML = ElementId;
Or jQuery:
$('#valt_element_id').html(ElementId);
You mentioned:
But on some field i just want to show the data, not to be edited . Why not use readonly attribute in input rather than replacing it with a span ?

How to render HTML with jQuery from an AJAX call

I have a select box with a list of books. The user can select a book and hit the submit button to view the chapters on a separate page.
However, when the user changes the select box, I would like a partial page refresh to display the past notes the user entered on the book, and allow the user to write a new note for that book. I do not want the review and creation of notes for a particular book done on the next page with the chapters, as it will clutter it up.
I'm using Python/Bottle on the backend and its SimpleTemplate engine for the front end.
Currently, when the select box is changed, an ajax call receives a Json string containing the book information and all the notes. This json string is then converted into a json object via jQuery.parseJson().
What I would like to be able to do is then loop over the notes and render a table with several cells and rows.
Would I have to do this in jQuery/js (instead of bottle/template framework) ? I assume so as I only want a partial refresh, not a full one.
I'm looking for a piece of code which can render a table with variable numbers of rows via jQuery/js from a json object that was retrieved with ajax.
<head>
<title>Book Notes Application - Subjects</title>
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
<script>
$(document).ready(function(){
$('#subject_id').change(function(){
var subject_id = $(this).val();
$.ajax({
url : "subject_ajax?subject_id=" + subject_id,
success : function(data) {
alert(data)
json = jQuery.parseJSON(data);
},
error : function() {
alert("Error");
}
});
})
})
</script>
</head>
<body>
<!-- CHOOSE SUBJECT -->
<FORM action="/books" id="choose_subject" name="choose_subject" method="POST">
Choose a Subject:
<select name="subject_id" id="subject_id">
% for subject in subjects:
<option value="{{subject.id}}">{{subject.name}}</option>
% end
</select><input type="submit" name="sub" value="Choose Subject"/>
<BR />
</FORM>
This greatly depends on how your JSON and HTML are formatted. But with a table somewhere like:
<table id="books">
<tr>
<th>Chapter</th>
<th>Summary</th>
</tr>
</table>
You could do something like:
$(function(){
$('#choose_subject').submit(function () {
var subject_id = $(this).val();
$.getJSON("subject_ajax?subject_id=" + subject_id, function(data) {
console.log(data);
$.each(data.chapters, function (index, chapter) {
$('#books').append('<tr><td>' + chapter.title + '</td><td>' + chapter.summary + '</td></tr>');
})
});
return false;
})
})
This supposes JSON like:
{
"notes": [
"Note 1",
"Note 2"
],
"chapters": [
{
"title": "First chapter",
"summary": "Some content"
},
{
"title": "Second chapter",
"summary": "More content"
}
]
}
Other notes:
If you use HTML 4 or earlier, keep all your tags in upper case. If you're using XHTML or HTML5, keep all your tags in lower case.
You don't need $(document).ready(function () {...}), with recent versions of jQuery $(function () {...} ) works the same and it's easier to read.
You can use $.get instead of $.json if you're only using the success state (as you are here). And if you're confident that the data you'll get is valid JSON, you can use getJSON instead of get. It will parse the JSON for you deliver it to you as a JavaScript object automatically.
It's usually more convenient to use console.log rather than alert when you're testing. Actually, it's usually a bad idea in general to ever use alert.
I'm not familiar with Python/Bottle or its SimpleTemplate engine, but you could consider generating the html for the table on the server side and returning it in the ajax response, rather than returning JSON.
var subject_id = $(this).val();
$.ajax('subject_ajax', {
type: 'get',
data: { subject_id: subject_id },
dataType: 'html',
success : function(html) {
// Insert the html into the page here using ".html(html)"
// or a similar method.
},
error: function() {
alert("Error");
}
});
When calling .ajax():
The "type" setting defaults to "get", but I prefer to explicitly set it.
Use the "data" setting for the ajax call to specify the URL parameter.
Always specify the "dataType" setting.
I also recommend you perform the ajax call in an on-submit handler for the form, and add an on-change handler for the select that submits the form.
$(document).ready(function(){
$('#subject_id').change(function() {
$(this.form).submit();
});
$('#choose_subject').submit(function(event) {
event.preventDefault();
var subject_id = $('#subject_id').val();
if (subject_id) {
$.ajax(...);
}
});
});
This way your submit button should work in case it is clicked.
There are a few things you need to look at:
1) Is your SimpleTemplate library included?
2) Have you compiled your template via compileTemplate()?
Once you know your library is included (check console for errors), pass your data returned to your success handler method, compile your template, that update whichever element you are trying to update.
I'm not sure that you want to update the same element that you're defining your template in.
$(document).ready(function(){
$('#subject_id').change(function(){
var subject_id = $(this).val();
$.ajax({
url : "subject_ajax?subject_id=" + subject_id,
success : function(data) {
var template_data = JSON.parse(data);
var template = $('#subject_id').toString(); // reference to your template
var precompiledTemplate = compileTemplate(template);
var result = precompiledTemplate(template_data);
$('#subject_id').append(result);
},
error : function() {
alert("Error");
}
});
})
})
You might also try moving your template out of the element you're trying to update like this:
<script type="text/template" id="subject-select-template">
% for subject in subjects:
<option value="{{subject.id}}">{{subject.name}}</option>
% end
</script>
Then just create a blank select element like so:
<select id="select_id"></select>
Update references. Anyway, hope this is helpful. It should work but I can't test without your specific code ;)
Also, check out this demo example if you haven't yet:
https://rawgithub.com/snoguchi/simple-template.js/master/test/test.html

Categories

Resources