JSTL Spring MVC Recursive Form JSP - java

I am trying to build a dynamic form generator getting a json as an input. The json comes from an AWS device shadow and I want to build a form which allows the user to manipulate the desired state of it.
The controller class looks like this:
#Controller
public class FormGeneratorController {
#RequestMapping(value = "/form/textfield", method = RequestMethod.GET, params = {"parentName", "propertyName", "propertyValue"})
public ModelAndView getTextField(#RequestParam(value = "parentName", required = false, defaultValue = "") String parentName,
#RequestParam(value = "propertyName", required = false, defaultValue = "") String propertyName,
#RequestParam(value = "propertyValue", required = false, defaultValue = "") String propertyValue) {
ModelAndView model = new ModelAndView("jsonConfigTextField");
model.addObject("parentName", parentName);
model.addObject("propertyName", propertyName);
model.addObject("propertyValue", propertyValue);
return model;
}
#RequestMapping(value = "/form/objectfield", method = RequestMethod.GET, params = {"parentName", "propertyName", "propertyValue"})
public ModelAndView getObjectField(#RequestParam(value = "parentName", required = false, defaultValue = "") String parentName,
#RequestParam(value = "propertyName", required = false, defaultValue = "") String propertyName,
#RequestParam(value = "propertyValue", required = false, defaultValue = "") String propertyValue) {
ModelAndView model = new ModelAndView("jsonConfigObjectField");
JSONObject settings = new JSONObject(propertyValue);
model.addObject("parentName", parentName);
model.addObject("propertyName", propertyName);
model.addObject("propertyValue", settings);
return model;
}
#RequestMapping(value = "/form", method = RequestMethod.GET)
public ModelAndView getForm() {
ModelAndView model = new ModelAndView("settingsForm");
model.addObject("parentName", "");
model.addObject("propertyName", "root");
model.addObject("propertyValue", "{\"light\":{\"test\":\"t\"}}");
return model;
}
}
settingsForm.jsp:
<form>
<c:import url="/form/objectfield?parentName=${parentName}&propertyName=${propertyName}&propertyValue=${propertyValue}"></c:import>
<input type="submit" value="Absenden">
</form>
jsonObjectField.jsp:
<c:forEach items="${propertyValue.keys()}" var="propertyKey">
<c:if test="${propertyValue.get(propertyKey).getClass().name == 'java.lang.String'}">
<c:import url="/form/textfield?parentName=${parentName}&propertyName=${propertyKey}&propertyValue=${propertyValue.getString(propertyKey)}" ></c:import>
</c:if>
<c:if test="${propertyValue.get(propertyKey).getClass().name == 'org.json.JSONObject'}">
<c:import url="/form/objectfield?parentName=${parentName}&propertyName=${propertyKey}&propertyValue=${propertyValue.getJSONObject(propertyKey)}" ></c:import>
</c:if>
</c:forEach>
jsonConfigTextField.jsp:
<div class="form-group">
<label for="<c:out value="${parentName}_${propertyName}"></c:out>"><c:out value="${parentName}_${propertyName}"></c:out></label>
<input type="text" class="form-control" id="${parentName}_${propertyName}" name="${parentName}_${propertyName}" value="${propertyValue}">
</div>
This produces:
<form>
<div class="form-group">
<label for=",,,_test,light,root">test,light,root</label>
<input type="text" class="form-control" id=",,,_test,light,root" name=",,,_test,light,root" value="t,{"test":"t"},{"light":{"test":"t"}}">
</div>
<input type="submit" value="Absenden">
</form>
But I want to generate a form like this:
<form>
<div class="form-group">
<label for="root_light_test">root_light_test</label>
<input type="text" class="form-control" id="root_light_test" name="root_light_test" value="t">
</div>
<input type="submit" value="Absenden">
</form>
It seems like there is a problem with the JSONObject within in a JSONObject where the recursion I thought I would be doing somehow goes wrong. I do not understand where all the commas in the output are comming from.
Since recreating the issue is pretty hard I created a repository for you to clone and test the thing for yourself: https://github.com/faxe1008/JSTLRecursiveForm
I really would appreciate any help on this, today I spent 4 hours trying to figure out the problem...

You should parse the JSON input in your controller, with Jackson for example, and add the data to simple objects. These you should pass to your model, which is available in your view. In you view simply iterate the created objects

Related

Save all object with th:object

I want to sent object with model.addAttribute and get all object's variable after saving.
Controller
#GetMapping(value = "/passport/details/{id}")
#PreAuthorize("isAuthenticated()")
public String passportDetails(Model model, #PathVariable(name = "id") Long id) {
PassportRequest passportRequest = businessService.getPassportRequestById(id);
model.addAttribute("passport", passportRequest);
return "/user/passport/create";
}
#PostMapping(value = "/passport/save")
#PreAuthorize("isAuthenticated()")
public String savePassport(PassportRequest passport) {
businessService.savePassportRequest(passport);
return "redirect:/passport/details/" + passport.getId();
}
html-code:
<form enctype="multipart/form-data" method="post" th:action="#{/passport/save}"
data-parsley-validate="" role="form"
novalidate="" th:object="${passport}" id="sign-form">
<input type="hidden" th:field="*{id}">
<input type="hidden" th:field="*{stage}">
<div class="col-6 m-input-group">
<label>Кем командирован</label>
<input type="text" name="postedBy" placeholder="Введите" th:field="*{postedBy}" required>
</div>
</form
The problem is I need to make <input type="hidden" th:field="*{objectVariable}"></input> to every variable to send them. Is there any easier way to do?
One way of doing this is annotating your controller with #SessionAttributes("passport") (which means it will store the object on the session and keep all it's properties during this controllers methods).
You might also need to change
public String savePassport(PassportRequest passport) {
to
public String savePassport(#ModelAttribute("passport") PassportRequest passport) {
to make sure all the attributes line up.

HTTP Status 400 - Required String parameter 'clientId' is not present

I have Spring MVC application with this controller method.
#RequestMapping(value = "/saveMe", method = RequestMethod.POST)
public #ResponseBody String saveMe(#RequestParam(value = "clientId") String strClientId,#RequestParam(value = "clientName") String strClientName,#RequestParam(value = "custBaseNo") String strCustBaseNo, #RequestParam(value = "category") String strCategory,#RequestParam(value = "clientCpt") String strClientCpt, #RequestParam(value = "pbk") String strPbk,#RequestParam(value = "prk") String strPrk,#RequestParam(value = "fileAct") int intFileAct, #RequestParam(value = "b2b") int intB2b,#RequestParam(value = "collection") int intCollection, #RequestParam(value = "primAccNo") String strPrimAccNo,#RequestParam(value = "accFromAcct") String strAccFromAcct,#RequestParam(value = "accToAcct") String strAccToAcct,#RequestParam(value = "intCount") int intCount,#RequestParam(value = "productId") String strProductId,HttpServletRequest request){
String strStatus ="";
System.out.println("strClientId is :::"+strClientId);
strStatus = sabService.saveDetails(strClientId,strClientName,strCustBaseNo,strCategory,strClientCpt,strPbk,strPrk,intFileAct,intB2b,intCollection,strPrimAccNo,strAccFromAcct,strAccToAcct,intCount,strProductId);
String[] strChkService = new String[intCount];
String[] strAccNO = new String[intCount];
int[] intTrnsLimit = new int[intCount];
String[] strProtcl = new String[intCount];
for(int j=1;j<=intCount;j++){
strChkService[j] = request.getParameter("chkService"+j)==null?"":request.getParameter("chkService"+j);
strAccNO[j] = request.getParameter("accountNo"+j)==null?"":request.getParameter("accountNo"+j);
intTrnsLimit[j] = Integer.parseInt(request.getParameter("transactionLimit"+j)==null?"0":request.getParameter("transactionLimit"+j));
strProtcl[j] = request.getParameter("protocol"+j)==null?"":request.getParameter("protocol"+j);
strStatus = sabService.saveServices(strClientId,strProductId,strChkService[j],strAccNO[j],intTrnsLimit[j], strProtcl[j] );
}
return "success";
}
While submitting the form I'm getting this error.
HTTP Status 400 - Required String parameter 'clientId' is not present
Can anyone please help me...Thanks in advance...
jquery-
$("#client-maint-form").attr("action","sabb/saveMe");
$("#client-maint-form").submit();
form-
<form id="client-maint-form" class="form-horizontal" enctype="multipart/form-data" method="POST">
i have also tried with GET ...but getting this error
HTTP Status 405 - Request method 'GET' not supported
Here is the form
<form id="client-maint-form" class="form-horizontal" enctype="multipart/form-data" method="POST">
<div class="box-body">
<div class="form-group">
<label for="client-id" class="col-sm-3 control-label">Client Id<a style="color: red">*</a></label>
<div class="col-xs-4">
<input class="form-control" name="clientId" id="client-id" required="true" placeholder="Client Id" type="text">
</div>
</div>
<div class="form-group" id="password-div-add-update">
<label for="client-name" class="col-sm-3 control-label">Client Name<a style="color: red">*</a></label>
<div class="col-xs-4">
<input class="form-control" name="clientName" id="client-name" required="true" placeholder="Client Name" type="text">
</div>
</div>
</form>

Neither BindingResult nor plain target object for bean name when running application

index.jsp
<f:form action="emp_change.htm" method="POST" commandName="index">
<div id="login_box">
<div id="form_val">
<div class="label">Username:</div>
<div class="control"><f:input path="emailId" /></div>
<div style="clear:both;height:0px;"></div>
<div class="label">Password:</div>
<div class="control"><f:input path="password" type="password" /></div>
<div style="clear:both;height:0px;"></div>
<div id="msgbox"></div>
<div id="login_foot">
<input type="submit" name="action" id="login" value="Login" class="send_button" />
</div>
</div>
</div>
</f:form>
AdminInfoControl.java
#Controller
public class AdminInfoControl {
private AdminInfoService service;
#RequestMapping(value = "/emp_change", method = RequestMethod.POST)
public String doActions(#ModelAttribute JtAdminInfo emp, BindingResult result, #RequestParam String action, Map<String, Object> map) {
service = new AdminInfoService();
JtAdminInfo empResult = new JtAdminInfo();
switch (action.toLowerCase()) {
case "login":
JtAdminInfo search = service.getFindAdmin(emp.getEmailId());
empResult = search != null ? search : new JtAdminInfo();
break;
}
map.put("index", empResult);
map.put("empList", service.getAll());
return "index";
}
}
I'm getting following error :
Neither BindingResult nor plain target object for bean name 'emp_change' available as request attribute
Anyone please help me to correct this. Please let me know, if information is not sufficient.
Just answered on almost the same question.. You are obtaining emp_change as a model attribute in doActions method but you didn't set it as a model attribute previously. So, set your emp_change as a model attribute in some method that e.g. shows your index.jsp page. Something like this:
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView showIndex() {
ModelAndView mav = new ModelAndView("index");
mav.addObject("emp_change", new JtAdminInfo ());
return mav;
}
I have added following method in my controller and works fine.
#RequestMapping("/index")
public String setupForm(Map<String, Object> map) {
map.put("index", new JtAdminInfo());
return "index";
}

JQuery to update a <c:forEach> in Spring MVC

I сreated a jsp page with the table. I would like to refresh table after click the button using Jquery.
But in result i see two views at the same time. How to avoid this problem ?
My Controller
#Controller
#RequestMapping("/")
public class HelloController {
private final Logger log = LoggerFactory.getLogger(getClass());
#Autowired
private UserServiceDao userServiceDao;
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("Message","first");
model.addAttribute("list",userServiceDao.findAll());
log.trace("NUMBER:::::::::::::::::::::"+userServiceDao.findAll().size());
return "main";
}
#RequestMapping("/table")
public ModelAndView renderTable(HttpServletRequest request) {
String name = request.getParameter("nameSearch");
log.trace("1: "+name);
List<User> people = userServiceDao.find(name);
log.trace("2: "+people.size());
return new ModelAndView("main", "list", people);
}
}
MY view with the Jquery script
<body>
<div class="sear">
<input class=" int datasearch" type="search" value="an" id="dataSearch">
<input class="int search" type="button" value="Search" id="search">
<input class="int create" type="button" id="err" value="Create user">
</div>
<h1>List of users: </h1>
<div class="table" >
<c:forEach var="item" items="${list}">
<div class="row" >
<div id="tabl" class="cell" style="width:300px;"><c:out value="${item.name}"/>></div>
<div class="cell" style="width:100px;" ><input class="delete" type="button" value="Delete user"></div>
<div class="cell"><input class="edit" type="button" value="Edit user"></div>
</div>
</c:forEach>
</div>
<script type="text/javascript">
$('#err').click(function(){
window.location.href='/registration';
})
$('#search').click(function(){
$(function() {
var myTableContainer = $("#tabl");
var renderTable = function(container) {
var data = $('#dataSearch').val();
var postReqData = {}; // Create an empty object
postReqData['nameSearch'] = data;
$.get("/table",postReqData, function(data) {
container.empty().html(data);
})
};
/* This is called on document ready */
renderTable(myTableContainer);
/* Use the same renderTable function when the refresh button is clicked */
$("#search").click(function() {
renderTable(myTableContainer);
});
})
})
Ok, this might be a bit too long for comments.
Your main problem is that both #RequestMapping(method = RequestMethod.GET) and #RequestMapping("/table") render the same view.
That is: the view containing all your search inputs, <c:forEach> table and javascript.
So when you do the search and when the ajax call returns, you replace contents of div#tabl with all those search inputs, <c:forEach> and javascript.
You end up with two pieces of everything nested in the wrong way.
My advice would be to do one RequestMapping that renders the basic jsp, and the other one that renders only the search results (or even returns json and render it as html in javascript).

associate form with Object

#ModelAttribute annotation(Spring) allows for html to create an object.
For example there is a class
class Vasya{
int id;
String name;
//set get
}
and html form
<form action='path'>
<input type='text' name = 'id'/>
<input type='text' name = 'name'/>
<input type='submit'/>
</form>
#controller method:
#RequestMapping("/path")
public String processSkill( #ModelAttribute Vasya vasya) {...}
here it works.
Question:
how can I write html form using *checkbox*es for id and name that my controller method works?
Dont understand how to pass id using checkbox, but you can pass checkbox value that way:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String form(#RequestParam(required = false) Integer check) {
if(check != null) { // if checkbox is not selected it is null
System.out.println(check);
}
return "your-view";
}
jsp:
<form action="${home}/test" method="POST">
<input type="checkbox" value="1" name="check" />
<input type="submit" />
</form>

Categories