I am calling controller through javascript function like below and I want to return some value(controller execution time) from controller to same javascript function without using return statement or any other way?
function myFunction(){
var form123 = document.getElementById("myFormSubmit");
form123 .action="userDetailsList";
form123 .method="POST";
form123 .submit();
}
use GSON package this will help output a json String
import com.google.gson.Gson;
#ResponseBody This will not return a view it will return a string to the browser (technically) which jquery will read..
#RequestMapping(value = "/URLHERE", method = RequestMethod.POST)
public #ResponseBody
String CheckAdapter(HttpServletRequest request, HttpSession session) {
Map<String, Object> hm = new HashMap<>();
String a = your Logic here;
hm.put("string", a);
return new Gson().toJson(hm);
}
This is the ajax part
$.ajax({
type: "POST",
url: "URLHERE",
dataType: 'JSON',
success: function (data) {
console.log(data);
}
});
What is ajax?
AJAX, or Asynchronous Javascript And XML, is a client side technique for communication with a web server. ... Instead of making a URL request for another whole page, you use JavaScript to talk to the server and receive smaller pieces of information that can range from HTML to other data formats like JSON/XML/Etc
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 am trying to create controller actions which will return either JSON or partial html depending upon a parameter. What is the best way to get the result returned to an MVC page asynchronously?
In your action method, return Json(object) to return JSON to your page.
public ActionResult SomeActionMethod() {
return Json(new {foo="bar", baz="Blech"});
}
Then just call the action method using Ajax. You could use one of the helper methods from the ViewPage such as
<%= Ajax.ActionLink("SomeActionMethod", new AjaxOptions {OnSuccess="somemethod"}) %>
SomeMethod would be a javascript method that then evaluates the Json object returned.
If you want to return a plain string, you can just use the ContentResult:
public ActionResult SomeActionMethod() {
return Content("hello world!");
}
ContentResult by default returns a text/plain as its contentType.
This is overloadable so you can also do:
return Content("<xml>This is poorly formatted xml.</xml>", "text/xml");
I think you should consider the AcceptTypes of the request. I am using it in my current project to return the correct content type as follows.
Your action on the controller can test it as on the request object
if (Request.AcceptTypes.Contains("text/html")) {
return View();
}
else if (Request.AcceptTypes.Contains("application/json"))
{
return Json( new { id=1, value="new" } );
}
else if (Request.AcceptTypes.Contains("application/xml") ||
Request.AcceptTypes.Contains("text/xml"))
{
//
}
You can then implement the aspx of the view to cater for the partial xhtml response case.
Then in jQuery you can fetch it passing the type parameter as json:
$.get(url, null, function(data, textStatus) {
console.log('got %o with status %s', data, textStatus);
}, "json"); // or xml, html, script, json, jsonp or text
Another nice way to deal with JSON data is using the JQuery getJSON function. You can call the
public ActionResult SomeActionMethod(int id)
{
return Json(new {foo="bar", baz="Blech"});
}
Method from the jquery getJSON method by simply...
$.getJSON("../SomeActionMethod", { id: someId },
function(data) {
alert(data.foo);
alert(data.baz);
}
);
I found a couple of issues implementing MVC ajax GET calls with JQuery that caused me headaches so sharing solutions here.
Make sure to include the data type "json" in the ajax call. This will automatically parse the returned JSON object for you (given the server returns valid json).
Include the JsonRequestBehavior.AllowGet; without this MVC was returning a HTTP 500 error (with dataType: json specified on the client).
Add cache: false to the $.ajax call, otherwise you will ultimately get HTTP 304 responses (instead of HTTP 200 responses) and the server will not process your request.
Finally, the json is case sensitive, so the casing of the elements needs to match on the server side and client side.
Sample JQuery:
$.ajax({
type: 'get',
dataType: 'json',
cache: false,
url: '/MyController/MyMethod',
data: { keyid: 1, newval: 10 },
success: function (response, textStatus, jqXHR) {
alert(parseInt(response.oldval) + ' changed to ' + newval);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error - ' + errorThrown);
}
});
Sample MVC code:
[HttpGet]
public ActionResult MyMethod(int keyid, int newval)
{
var oldval = 0;
using (var db = new MyContext())
{
var dbRecord = db.MyTable.Where(t => t.keyid == keyid).FirstOrDefault();
if (dbRecord != null)
{
oldval = dbRecord.TheValue;
dbRecord.TheValue = newval;
db.SaveChanges();
}
}
return Json(new { success = true, oldval = oldval},
JsonRequestBehavior.AllowGet);
}
To answer the other half of the question, you can call:
return PartialView("viewname");
when you want to return partial HTML. You'll just have to find some way to decide whether the request wants JSON or HTML, perhaps based on a URL part/parameter.
Alternative solution with incoding framework
Action return json
Controller
[HttpGet]
public ActionResult SomeActionMethod()
{
return IncJson(new SomeVm(){Id = 1,Name ="Inc"});
}
Razor page
#using (var template = Html.Incoding().ScriptTemplate<SomeVm>("tmplId"))
{
using (var each = template.ForEach())
{
<span> Id: #each.For(r=>r.Id) Name: #each.For(r=>r.Name)</span>
}
}
#(Html.When(JqueryBind.InitIncoding)
.Do()
.AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
.OnSuccess(dsl => dsl.Self().Core()
.Insert
.WithTemplate(Selector.Jquery.Id("tmplId"))
.Html())
.AsHtmlAttributes()
.ToDiv())
Action return html
Controller
[HttpGet]
public ActionResult SomeActionMethod()
{
return IncView();
}
Razor page
#(Html.When(JqueryBind.InitIncoding)
.Do()
.AjaxGet(Url.Action("SomeActionMethod","SomeContoller"))
.OnSuccess(dsl => dsl.Self().Core().Insert.Html())
.AsHtmlAttributes()
.ToDiv())
You may want to take a look at this very helpful article which covers this very nicely!
Just thought it might help people searching for a good solution to this problem.
http://weblogs.asp.net/rashid/archive/2009/04/15/adaptive-rendering-in-asp-net-mvc.aspx
PartialViewResult and JSONReuslt inherit from the base class ActionResult. so if return type is decided dynamically declare method output as ActionResult.
public ActionResult DynamicReturnType(string parameter)
{
if (parameter == "JSON")
return Json("<JSON>", JsonRequestBehavior.AllowGet);
else if (parameter == "PartialView")
return PartialView("<ViewName>");
else
return null;
}
For folks who have upgraded to MVC 3 here is a neat way
Using MVC3 and Json
public ActionResult GetExcelColumn()
{
List<string> lstAppendColumn = new List<string>();
lstAppendColumn.Add("First");
lstAppendColumn.Add("Second");
lstAppendColumn.Add("Third");
return Json(new { lstAppendColumn = lstAppendColumn, Status = "Success" }, JsonRequestBehavior.AllowGet);
}
}
Flexible approach to produce different outputs based on the request
public class AuctionsController : Controller
{
public ActionResult Auction(long id)
{
var db = new DataContext();
var auction = db.Auctions.Find(id);
// Respond to AJAX requests
if (Request.IsAjaxRequest())
return PartialView("Auction", auction);
// Respond to JSON requests
if (Request.IsJsonRequest())
return Json(auction);
// Default to a "normal" view with layout
return View("Auction", auction);
}
}
The Request.IsAjaxRequest() method is quite simple: it merely checks the HTTP headers for the incoming request to see if the value of the X-Requested-With header is XMLHttpRequest, which is automatically appended by most browsers and AJAX frameworks.
Custom extension method to check whether the request is for json or not so that we can call it from anywhere, just like the Request.IsAjaxRequest() extension method:
using System;
using System.Web;
public static class JsonRequestExtensions
{
public static bool IsJsonRequest(this HttpRequestBase request)
{
return string.Equals(request["format"], "json");
}
}
Source : https://www.safaribooksonline.com/library/view/programming-aspnet-mvc/9781449321932/ch06.html#_javascript_rendering
I have to call and fetch data from rest API with in every second. So I call the method with time 1 sec. As follows.
var myVar = setInterval(function(){ getData1() }, 1000);
Following is my Javascript function which call the controller.
function getData1(){
var url=CONTEXT_ROOT+"/login/getdashboarddata1";
$.ajax({
type: "POST",
url: url,
contentType: "application/json",
dataType: "json",
data:{},
success: function(data){
alert(data);
},
error: function(e){
//alert(e);
}
});
}
This is my controller code
#RequestMapping(value="/getdashboarddata1", method=RequestMethod.POST)
public JSONObject #ResponseBody getDashboardData1() throws JsonParseException, JsonMappingException, NullPointerException{
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/r_f22bc0ac1fe48bce/dataService/lastdata/";
String user = restTemplate.getForObject(url, String.class);
System.out.println("user: "+user);
JSONObject obj = null;
try {
obj = new JSONObject(user);
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
If I run the program then jsp does not shows any alert. but if I change the return type of in controller to String then it shows proper JSON string in ajax response.
i.e. [{"sno":"3618","data":"01","datetime":"2017-04-05 12:33:26.266"}]
If i carry this, then I am unable to get data from JSON string.
please tell me what is my issue. or is there any other way to do this.?
You have json array
[{"sno":"3618","data":"01","datetime":"2017-04-05 12:33:26.266"}]
Then access it using index:
data[0].sno
Simply return a String from getDashboardData1()
And then in AJAX success callback:
JSON.parse(data)[0]['sno'];
please tell me what is my issue. or is there any other way to do
this.?
You can't access attributes of a string literal, it has to be a json object.
I am building an ASP.NET MVC application It currently has a button that once clicked does an Ajax call to the controller as so:
function getData() {
$.ajax({
url: "/Home/GetData/",
type: "POST",
contentType: 'application/json',
success: function (data){
//need to do stuff here
}
});
}
The controller then initializes a class, converts it to XML and then converts that to the following dictionary (There is a reason for this):
public ActionResult GetData()
{
List<People> peeps = GetPeeps();
string xml = ToXml(peeps);
Dictionary<string,List<string>> stuff = ToDictionary(xml);
return Json(stuff);
}
I would like to be able to 'Do stuff' with this data client side with javascript.
The APIs I have to work with Server side return XML data.
The APIs I have to work with Client side require string arrays. (Hence the conversions)
Is there a way to use the dictionary i've defined above client side? Could someone perhaps expand from this (if possible) to add to the ajax call a small method that prints the contents of the dictionary to a message box? just to give me a starting point from how to use the dictionary in javascript.
Thanks in advance
You can try in the ajax call as follow:
function getData() {
$.ajax({
url: "/Home/GetData/",
type: "POST",
contentType: 'application/json',
success: function (data){
console.log(data.key1); // value for key1
//or to list all values
for(var key in data){
console.log(data[key]);
}
}
});
}
Controller (for explanation purposes):
public ActionResult GetData()
{
//List<People> peeps = GetPeeps();
//string xml = ToXml(peeps);
//Dictionary<string,List<string>> stuff = ToDictionary(xml);
Dictionary<string,List<string>> stuff = new Dictionary<string, List<string>>
{
{"key1", new List<string> {"a", "b", "c"}},
{"key2", new List<string> {"d", "e", "f"}},
};
return Json(stuff);
}
I hope this is clear enough. Let me know how you go :)