I'm using the jQuery UI autocomplete to show suggestions for a text input field.
The suggestions are stored in a Javascript array called suggestions.
I'm trying to fetch the string values for the suggestions array from a database, but I can't convert the List object to a Javascript array.
The Javascript:
var suggestions = [];
$.get('/mywebapp/autocompleteplayer.html', function(data){
parsed = JSON.parse(data);
suggestions = parsed.split(",");
}, "json");
$('#autocompleted').autocomplete({
data: suggestions,
minLength: 3
});
The Spring MVC controller:
#Controller
public class AutocompletePlayerController {
#RequestMapping(value = "/autocompleteplayer")
public List<String> getPlayerSuggestions(){
List<String> myList;
//code that fills myList with all of the players' full names from the database, omitted for brevity
return myList;
}
}
I know I'm not parsing the AJAX response properly, since I've checked from the browser console that the suggestions array has 0 elements. Can anyone help me? What am I doing wrong here?
You need to use it like this in your js (data is the response entity, not the data - it's in data.data) :
$.get('/mywebapp/autocompleteplayer', function(data){
suggestions = data.data;
$('#autocompleted').autocomplete({ // not sure how to use your plugin
data: suggestions,
minLength: 3
});
}, "json");
And in your spring controller, add the #ResponseBody Annotation
#RequestMapping(value = "/autocompleteplayer")
#ResponseBody
public List<String> getPlayerSuggestions(){
List<String> myList;
//code that fills myList with all of the players' full names from the database, omitted for brevity
return myList;
}
There's no need to JSON.parse anything, jquery already did this.
/mywebapp/autocompleteplayer.html also sounds wrong. The route is autocompleteplayer without .html.
Other than that, suggestions is created async. So your data in autocomplete will always be empty. I didn't use that plugin myself so there might be an update function for the data, otherwise try to put it in the $.get() functions callback.
You can return json array as String in java
#Produces("application/json")
public String getPlayerSuggestions(){
....
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String jsonString = gson.toJson(myList);
return jsonString;
}
You need to modify your controller like this:
#RequestMapping(value = "/autocompleteplayer", method=RequestMethod.GET)
#ResponseBody
public String getPlayerSuggestions(){
List<String> myList;
JSONArray jsonArray = new JSONArray();
for(String item: myList){
JSONObject jsonObj = new JSONObject();
jsonObj.put("Item", item);
jsonArray.put(jsonObj);
}
return jsonArray.toString();
}
then you can handle your values easy with JSON.
Regards,
Related
What is the best way to access a java Map from javascript while using Spring MVC?
I'm building a webpage where depending on the values you chose from a checkbox, a dynamic text will appear in another div with further details regarding that option by using getElementById("element").innerHTML=${var}.
I'm using Maps to populate the checkbox options, and it does works fine in JSPs but simply won't work in javascript scriptlets or external .js files. It just understands it as a string, not as a Map or Array.
The following code is what I've got so far:
Properties file:
checkBoxItems={'0':'The Value'}
myMapObject={'0','Map Stuff'}
In Controller java file:
#Controller
#RequestMapping(value = "/example")
public Class ExampleController
{
#Value("#{${checkBoxItems}}")
Map<String, String> checkBoxOptions;
#Value("#{${myMapObject}}")
Map<String, String> myMapObject;
#RequestMapping(value = "/newExample", method = RequestMethod.GET)
public String Hello(Model model)
{
model.addAttribute("checkBoxOptions", checkBoxOptions);
model.addAttribute("myMapObject", myMapObject);
return "view";
}
}
in JSP: (I've simplified to show what I aim to achieve)
<form:select class="custom-select" id="metodologia" path="metodologia"
onchange="FillWithComplement('${myMapObject}')">
<form:option value="-">Select an Option</form:option>
<form:options items="${checkboxOptions}"/>
</form:select>
In the first javascript trial:
<script>
function FillWithComplement(MapObject)
{
document.getElementById("div").innerHTML = MapObject;
}
</script>
the output is:
{0=Map Stuff}
And it also doesn't work if I do:
<script>
function FillWithComplement(MapObject)
{
var newMap = new Map(MapObject);
document.getElementById("div").innerHTML = newMap;
}
</script>
And I am aware I might not have enough javascript knowledge do handle this correcty.
Thanks.
EDIT:
As proposed by Yan Khonski, passing data as JSON by asynchronous request (ajax) worked with minor changes.
dataType: 'json' returns a JSON object, so it is needless to implement a JSON parsing method.
The final code:
var globalMetodologiaComplemento;
$(document).ready(function () {
$.ajax({
type: 'GET',
url: '/gla/getMet',
dataType: 'json',
success: function (data) {
globalMetodologiaComplemento = data;
console.log(globalMetodologiaComplemento[0]);
}
});
});
(...)
You can have a REST end-point which returns data in JSON format. Then your client - javascript code, will make an asynchronous request (after the page has loaded) to the rest end-point and get the data. Then js code will parse JSON into object and can work with it.
1) Controller returns model and view. The view is a JSP page.
#Controller
#RequestMapping(value = "/example")
public Class ExampleController
{
#Value("#{${checkBoxItems}}")
Map<String, String> checkBoxOptions;
#Value("#{${myMapObject}}")
Map<String, String> myMapObject;
#RequestMapping(value = "/newExample", method = RequestMethod.GET)
public String Hello(Model model) {
model.addAttribute("checkBoxOptions", checkBoxOptions);
model.addAttribute("myMapObject", myMapObject);
return "view";
}
#ResponseBody
#GetMapping("/additional-data")
public String getData() {
return objectMapper.writeValueAsString(yourObject);
}
}
Check Jackson library to serialize objects into JSON.
2) Once jsp page is loaded, you can make an asynchronous (AJAX) request to another end-point in your controller. This endpoint will return JSON data (you will have to serialize your object into JSON).
https://api.jquery.com/jquery.ajax/
How to parse JSON data with jQuery / JavaScript?
https://stackoverflow.com/a/32593283/1839360
$(document).ready(function(){
$.ajax({
type: 'GET',
url: 'http:localhost:8080/example/additional-data',
dataType: 'json',
success: function (data) {
//data downloaded so we call parseJSON function
//and pass downloaded data
var object = $.parseJSON(data); // use browser debugger to see that properties the object has
}
});
});
3) Your client JS code will receive a response from AJAX call and parse the data.
By using jQuery, I am trying to save my string array in backend and following is my approach.
1.Using jQuery ajax sending array.
var tagTexts = $(ul li.select2-selection__choice")
.toArray()
.map(function(i){
return i.innerText;
});
tagTexts = tagTexts.join(',');
$.ajax({
type: 'POST' ,
url: '/tag/tagList',
dataType: 'json',
data: {
tagTexts: tagTexts
},
error: function(err) {
console.log(err);
},
success: function(response) {
//Process Response
}
});
2.In backend it is retrieved as follows:
#ResponseBody
#RequestMapping(value = "/tag/tagList", method = RequestMethod.POST)
public String saveTagList(HttpServletRequest request,
#RequestParam(value = "tagTexts", required = false)List<String>tagTexts) {
System.out.println(tagTexts);
String response = tagService.saveTags(tagTexts);
return response;
}
a) Using array join method
Following is the string array captured:
["Drone", "Richard Feynman, PHD", "Yatch"]
After using array join method this gets changed as follows:
Drone,Richard Feynman, PHD,Yatch
In java execution (backend) this gets displayed as follows:
[Drone, Richard Feynman, PHD, Yatch]
b) Using JSON.stringify method
After using JSON.stringify method, the captured array gets displayed as follows:
["Drone", "Richard feynman, PHD", "Yatch"]
This looks fine at js level but this entire line is considered as a string and it is displayed at the backend as follows:
[["Drone", "Richard feynman, PHD", "Yatch"]].
I am expecting my code to work as follows:
Comma character in raw data element captured should not split.
The entire array should not appear as a string in the backend.
Is there any better way to achieve this??
You can create a custom request object like this:
public class TagListRequest {
private List<String> tagTexts;
// getter and setter
}
You now can use this with #RequestBody in your request mapping:
#ResponseBody
#RequestMapping(value = "/tag/tagList", method = RequestMethod.POST)
public String saveTagList(#RequestBody TagListRequest request) {
System.out.println(request.getTagTexts());
String response = tagService.saveTags(request.getTagTexts());
return response;
}
Spring internally maps the JSON body of your request to the TagListRequest object using Jackson.
With this solution you do not need to parse the data manually using a separator.
Your javascript with JSON.stringify is correct solution. You just need to parse the JSON in java backend. For example,
import org.json.simple.JSONObject;
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(tagTexts);
See How to convert jsonString to JSONObject in Java for alternative ways how to parse JSON in java.
I have an array of JSON data already stored in a javascript variable as below:
var data = [{"a":153.15,"b":26.15,"c":item1},{"a":148.63,"b":23.45,"c":item2}];
function alertJson(data) {
Android.alertJson(data);
}
Then, I would like to do in java something like this:
#JavascriptInterface
public void alertJson(Array jsonStr) {
JSONArray jsonarray = new JSONArray(jsonStr);
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
String a = jsonobject.getString("a");
String b = jsonobject.getString("b");
String c = jsonobject.getString("c");
}
}
Now I am getting an error saying Array cannot be resolved to a type at Array jsonStr.
But the problem is jsonStr is undefined or not initialized. I want to get the value(array) of the javascript variable in jsonStr so I can use it in java. How can I achieve this?
By the way, I know how to bind javascript to android. I guess I just need a way to store the array in jsonStr somehow like using a function. Please help me.
try this
var data = JSON.parse('[{"a":153.15,"b":26.15,"c":item1},{"a":148.63,"b":23.45,"c":item2}]');
and
Android.alertJson(data.stringify());
public void alertJson(Array jsonStr) { // Change Array to String
Had this problem as well. Solution:
var data = [{"a":153.15,"b":26.15,"c":item1},{"a":148.63,"b":23.45,"c":item2}];
var myJSON = JSON.stringify(data );
Android.alertJson(myJSON);
On Android (Kotlin):
#JavascriptInterface
fun alertJson(myJSON: String) {
var jsonarray = JSONArray(myJSON)
// iterate through jsonarray
}
Java (not tested, but probably works)
#JavascriptInterface
public void alertJson(String myJSON) {
JSONArray jsonarray = new JSONArray(myJSON);
// iterate through jsonarray
}
I have a list of user inputs in an object 'data'. (for e.g data.username, data.password, data.age)
i am passing the data object to backend like this using angular.
var submits = "=" + JSON.stringify(data);
$.ajax({
type: "POST",
url: serviceURL,
data: submits
});
I am passing two more objects. selections and grid. how can i pass all these three together in one ajax call ? or do i have to transfer it independently. will it affect the performance if i transfer these details separately.
can i do something like this to send the object together in one ajax call?
var data = {};
data[0] = data1;
data[1] = data2;
How can i retrieve it separately at the server side using c# if at all they are passed together.
Heres the 3 objects that i need to pass
data -->> ["Raul","New York","31"]
selections-->> ["dy.txt","my.txt","yy.txt"]
grid--> ["sesion","id"]
Assuming you have a view model like this in your server side
public class CreateUserViewModel
{
public string UserName{set;get;}
public string Location {set;get;}
public int Age {set;get;}
}
public class RegisterViewModel
{
public CreateUserViewModel User {set;get;}
public List<string> Selections {set;get;}
public List<string> Grid {set;get;}
}
and an MVC action method like this
public ActionResult Create(RegisterViewModel model)
{
// read model and save and return some JSON response
}
You can simply build the javascript object which matches the structure of the view model and post it using angualr's $http service. No need to worrry about setting content-Type or Json stringifying it. Angualr will take care of it.
var model={ User : {} ,Selections :[], Grid=[] };
model.User.Age =23;
model.User.UserName ="test";
model.User.Location="New York";
model.Selections.push("dy.txt");
model.Selections.push("some.txt");
model.Grid.push("session");
model.Grid.push("id");
var url="replcaeUrltoYourActionMethodHere";
$http.post(url, model)
.then(function(response)
{
// do something with the response
// var result= response.data
});
You can send multiple objects / variables in ajax with:
var submits = "=" + JSON.stringify(data);
$.ajax({
type: "POST",
url: serviceURL,
data: {submits : submits, data1:data1, data2:data2}
});
In your C# you can access data1 and 2 in the same way as you handle submits now.
Depending of what is in data1 and data2 you might need to stringify it first.
second option:
You can also if you want to (but it is more ugly) use the stringify on everything at once and only pass the string:
data = {};
data["data1"] = data1;
data["data2"] = data2;
var submits = "=" + JSON.stringify(data);
Are you using WebApi or MVC on the server? If so, the simplest approach would be to create a class which holds the 3 entities you need to send and leverage the built-in model-binding
So in your example you list what looks to be a user form, selections and grids. I'm not really sure what the last two are but an example Model might look something like this:
public class UserSubmissionViewModel
{
public UserSubmissionViewModel() { }
public UserFormModel User {get;set;}
public SelectionsModel Selections { get; set; }
public GridModel Grids { get; set; }
}
Then on your web api controller or your MVC controller you'd have a method such as this:
public async Task<IHttpActionResult> Submit(UserSubmissionViewModel model)
And your javascript would resemble something roughly like this:
var toSend = {"UserFormModel":data, "SelectionsModel":selections, "GridModel":grids};
$.ajax({
type:"POST",
data:toSend, //<--- you might need to JSON.stringify this, cant test this code at the moment
url:serviceURL //<-- Calls your Submit method on the controller
});
As title,
i using angularjs to submit
my spring controller:
#RequestParam(value = "hashtag[]") hashtag[] o
above are work for array parameter but not an array object
my js script:
$http({
method: 'POST',
url: url,
data: $.param({
hashtag : [{label:"success",value:"ok"},{label:"success",value:"ok"},{label:"success",value:"ok"}],
}),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });
i observe from chrome, the form data is
hashtag[0][label]:success
hashtag[0][value]:10
hashtag[1][label]:success
hashtag[2][value]:10
hashtag[3][label]:success
hashtag[3][value]:10
But the Spring show me
org.springframework.web.bind.MissingServletRequestParameterException: Required hashtag[] parameter 'id[]' is not present
Previously i was able to receive an array of parameters, but not an object. so can someone enlighten me?
Try #RequestParam(value = "hashtag") hashtag[] o
Given that you have a class named hashtag havinf label and value attributes.
Try Using #ModelAttribute
Create a new Java class HashtagList like given below
public class HashTagList {
private List<HashTag> hashTag;
public List<HashTag> getHashTag() {
return hashTag;
}
public void setHashTag(List<HashTag> hashTag) {
this.hashTag = hashTag;
}
}
and in your controller method
#ModelAttribute("hashtag") HashTagList hashTagList
Is the java class name hashtag or HashTag ?
Because it is a POST request you can use #RequestBody annotation and create a DTO class to map the data you are sending or maybe even use your domain object.
For example, why not create reusable POJO class that can hold key->value pairs like:
#JsonPropertyOrder({"label", "value"})
public final class Pair<K,V> implements Map.Entry<K,V>, Serializable {
private final K key;
private final V value;
#JsonCreator
public Pair(#JsonProperty("label")K key, #JsonProperty("value")V value) {
this.key = key;
this.value = value;
}
// ... rest of the implementation
}
Note: I have assumed here you are using Jackson mapper, hence the JSON annotations.
Next step is to get the class that will hold the data structure you are sending from your client:
public class HashTags implements Serializable {
List<Pair<String, String>> hashtag = new ArrayList<>();
// ... rest of the implementation
}
Then in your controller you will have to do something like:
#RequestBody HashTags entity