I am trying to create a form in Spring MVC.
I would like to set action attribute of the <form> element dynamically using scriplet or something else.
MyForm:
<form:form id="myForm" modelAttribute="myFormBean"
action="<%=baseUrl%>/myFormControllerPattern" name="myForm">
<fieldset>
<table>
<tr>
<th>Name</th>
<td><form:input path="name" /></td>
</tr>
<tr>
<th>Age</th>
<td><form:input path="age"/></td>
</tr>
</table>
</fieldset>
</form:form>
Error:
attribute for %>" is not properly terminated
Found the solution. Thanks to jelies.
Added baseUrl in my controller like this:
model.setAttribute("baseUrl",url);
and then used it in my form in JSP:
<form action="${baseUrl}/myFormControllerPattern">
try to use javascript/jQuery trick:
var curl = document.location.pathname;
curl = curl.substring(0, curl.indexOf(".html"));
the first row will take your app address, then you cut the ".html" substring, thus enabling to add "/myFormControllerPattern" to the end of the string.
Change form action with javascript instead. Pass baseUrl as a model variable in your spring controller and use a javascript function like this to change form action:
function changeAction () {
var baseUrl = "${baseUrl}";
var form = document.getElementById("myForm");
form.action = baseUrl;
}
Hope it helps.
c:url tag can be usefull
include to jsp
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
and then
<form id="myForm" action="<c:url value="/myFormControllerPattern" />" name="myForm">
Related
I have 2 tables, city and hotel_details in my database. I am trying to fetch the data from these tables and populating inside a form for registering the customer. But I am getting "java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute" as error.
JSP file
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<head>
<title>Search Hotels</title>
</head>
<body>
<h4>Search Hotels</h4>
<form:form action="search">
<table>
<tr>
<td>City:</td>
<td>
<form:select path="cities">
<form:options items="${cities}" />
</form:select>
</td>
</tr>
<tr>
<td>Hotel:</td>
<td>
<form:select path="hotels">
<form:options items="${hotels}" />
</form:select>
</td>
</tr>
<tr>
<td>Date:</td>
<td>
<input type="date" id="date" name="date">
</td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Check Availability">
</td>
</tr>
</table>
</form:form>
Controller
#Controller
public class HomeController {
//need a controller method to show the initial HTML form
#Autowired(required=true)
private CityDAO cityDAO;
#Autowired(required=true)
private HotelDetailsDAO hotelDetailsDAO;
#RequestMapping("/")
public String showCheckAvailablityForm(Model theModel) {
// get customers from the dao
//List<City> theCities = cityDAO.getCities();
List<String> theCities = cityDAO.getCities();
Set<String> theHotels = hotelDetailsDAO.getHotels();
// add the customers to the model
theModel.addAttribute("cities", theCities);
theModel.addAttribute("hotels", theHotels);
//printing the data fetched
System.out.println("In HomeController showCheckAvailability method where city name is being fetched from city table");
theCities.forEach((n) -> System.out.println(n));
System.out.println("printing hotels");
for (String temp : theHotels) {
System.out.print(temp + " ");
}
return "checkAvailability-form";
}
#RequestMapping("/search")
public String searchResult(#RequestParam("cityName") String theCityName, #RequestParam("hotelName") String theHotelName,Model model) {
System.out.println("processed successfully");
return null;
}
}
When you use <form:form> attribute, it requires you to specify model object that should be bound to form tag. If you don't specify any model attribute default name is used as command.
Following is the description of form:form tag from spring-form.tld -
<attribute>
<description>Name of the model attribute under which the form object is exposed.
Defaults to 'command'.</description>
<name>modelAttribute</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>Name of the model attribute under which the form object is exposed.
Defaults to 'command'.</description>
<name>commandName</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
As you don't have any model object bound to form, try removing form:form tag and use HTML form tag and also make sure you match input parameter names with method parameter names. i.e -
<form action="search">
...
</form>
I am fetching some data with a Ajax request in my main JSP page.
Snippet of main.jsp
function gu(){
$.get('/admin/getAllUsers', {}, function(data) {
console.log(data); // see below
$("#allUsersData").html(data);
});
}
In my Spring controller I add all the users to a different JSP page.
Snippet of MainController.java
#RequestMapping(value = "/admin/getAllUsers", method = RequestMethod.GET)
public String getAllUsers(Model model){
List<User> users = userRepository.findAll();
System.out.println(users.size()); // output: 3
model.addAttribute("allUsers", users);
return "data/all-users";
}
Now in all-users.jsp I have a <c:forEach> which is supposed to load all users in a html table:
<table class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<c:if test="${not empty allUsers}">
<c:forEach items="${allUsers}" var="usr">
<tr>
<td>${usr.firstName}</td>
<td>${usr.lastName}</td>
<td>${usr.username}</td>
<td>${usr.creationDate}</td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
However, when I add the html coming from the request to my main JSP page, an empty table is shown. When I log the result of the Ajax request I find that the user data is inserted in the all-users.jsp:
<c:if test="true">
<c:forEach items="[User{id=1, username='username1', firstName='John', lastName='Doe', roles=[Role{id=1, name='ROLE_USER'}], creationDate=2018-02-19T08:58:13.333}, User{id=2, username='username2', firstName='John2', lastName='Doe2', roles=[Role{id=3, name='ROLE_USER'}], creationDate=2018-02-19T08:58:13.471}]" var="usr">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</c:forEach>
</c:if>
Why is it happening that the data is loaded into the data JSP page, but not shown when appending it to the main JSP page?
Can you check, maybe you haven't included the core tag library in your JSP file.
You will do this by inserting the following Line at the top of your file.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
I've input:
<g:form role="search" class="navbar-form-custom" method="post"
controller="simple" action="addEntry">
<div class="form-group">
<input type="text" placeholder="Put your data HERE"
class="form-control" name="InputData" id="top-search">
</div>
</g:form>
And table:
<table class="table table-striped table-bordered table-hover " id="editable">
<thead>
<tr>
<th>Name</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<g:render template="/shared/entry" var="entry"
collection="${entries}" />
</tbody>
</table>
Controller:
#Secured(['ROLE_USER', 'ROLE_ADMIN'])
class SimpleController {
def springSecurityService
def user
def index() {
user = springSecurityService.principal.username
def entries = Entry.findAllByCreatedBy(user)
[entries: entries]
}
def addEntry(){
def entries = Entry.findAllByCreatedBy(user)
render(entries: entries)
}
}
I just want to dynamically update the table with data from input string.
What is the best way?
Will be grateful for examples/solutions
You can update the table using AJAX with Grail's formRemote tag.
Input form
<g:formRemote
name="entryForm"
url="[controller: 'entry', action: 'add']"
update="entry">
<input type="text" name="name" placeholder="Your name" />
<input type="submit" value="Add" />
</g:formRemote>
HTML table
<table>
<thead>
<tr>
<th>Name</th>
<th>Created</th>
</tr>
</thead>
<tbody id="entry">
<g:render
template="/entry/entry"
var="entry"
collection="${entries}" />
</tbody>
</table>
Entry template
<tr>
<td>${entry.name}</td>
<td>${entry.dateCreated}</td>
</tr>
Controller
import org.springframework.transaction.annotation.Transactional
class EntryController {
def index() {
[entries: Entry.list(readOnly: true)]
}
#Transactional
def add(String name) {
def entry = new Entry(name: name).save()
render(template: '/entry/entry', collection: Entry.list(), var: 'entry')
}
}
How it works
When the add button is pressed the add controller method is called. The controller method creates the domain instance and renders the _entry.gsp template. But instead of refreshing the browser page, the template is rendered to an AJAX response. On the client side, the rendered template is inserted into the DOM inside of the tbody element with id entry, as defined in the formRemote tag by the update attribute.
Note that with this approach all of the entries are re-rendered, not just the new one. Rendering only the new one is a bit trickier.
Resources
Complete source code for my answer
Grails AJAX
Just to give you direction ( you are not showing any of your controller and js code.):
Create an action your controller ( the responsible controller) that will render the template /shared/entry by passing entries collection.
On submit of the form make ajax call to the action defined above, then replace the tbody html by the returned view fragment(template).
I have such this code inside my Spring MVC java controller class:
#RequestMapping(value = "jobs", method = { RequestMethod.GET })
public String jobList(#PathVariable("username") String username, Model model) {
JobInfo[] jobInfo;
JobStatistics js;
LinkedList<JobStatistics> jobStats = new LinkedList<JobStatistics>();
try {
jobInfo = uiClient.getJobs(username);
for (int i = 0; i < jobInfo.length; i++) {
js = uiClient.getJobStatistics(jobInfo[i].getJobId());
jobStats.add(js);
}
model.addAttribute("jobs", jobInfo);
model.addAttribute("jobStats", jobStats);
}
which uiClient will get some data from database using RMI ...
now I want to show the jobs & related statistic inside my JSP file using JSTL :
<c:set var="stats" value="${jobStats}" />
<c:forEach var="jobs" items="${jobs}">
<c:set var="jobID" value="${jobs.JobId}"/>
<table>
<tr class="tr1">
<td>${jobs.Topic}</td>
<td>${stats.get(i).No}</td>
</tr>
</table>
</c:forEach>
How do I get the LinkedList elements of Model inside my JSP using JSTL? There might be no no counter i been put in scope for me.
In my opinion, the right answer is a combination of both of the answers you got:
use varStatus attribute of c:foreach tag
but:
"get" is not a jstl function.
<c:forEach var="jobs" items="${jobs}" varStatus="i">
<c:set var="jobID" value="${jobs.jobId}"/>
<table>
<tr class="tr1">
<td>${jobs.topic}</td>
<td>${stats[i.index].no}</td>
</tr>
</table>
</c:forEach>
EDIT: this is the code finally used by the author of the question:
<c:set var="stats" value="${jobStats}" />
<c:forEach items="${jobs}" varStatus="i">
<c:set var="jobID" value="${jobs[i.index].jobId}"/>
<table>
<tr class="tr1">
<td>${jobs[i.index].topic}</td>
<td>${stats[i.index].no}</td>
<td>${jobID}</td>
</tr>
</table>
</c:forEach>
get is not a jstl function.
<td>${stats[i.index].No}</td>
use varStatus attribute of c:foreach tag
<c:forEach var="jobs" items="${jobs}" varStatus="i">
<c:set var="jobID" value="${jobs.JobId}"/>
<table>
<tr class="tr1">
<td>${jobs.Topic}</td>
<td>${stats.get(i.index).No}</td>
</tr>
</table>
</c:forEach>
I have some problems with taking a parameters from jsp page, when method POST occurs.
My JSP page looks like this:
....
<table border="1">
<tr>
<th>name</th>
<th>check</th>
</tr>
<c:forEach items="${things}" var="pair">
<tr>
<td>${things.name}</td>
<td><INPUT TYPE="CHECKBOX" NAME=items VALUE=${things.id} ></td>
</tr>
</c:forEach>
</table>
<form method="post">
<input type="submit" value="Check all" />
</form>
So, I want to take all checked "things" in table. In controller class I something like this (written in Spring):
....
#RequestMapping(method = RequestMethod.POST)
public String sumbitForm(#RequestParam("items") String[] items){
if(items!= null){
for(String item: items){
....
}
}
return "redirect:myPage";
}
But my app don't want to work with such RequesParam. It doesn't put the values of items parameter to it. (this method I took here http://www.go4expert.com/forums/showthread.php?t=4542)
Also I tried using #ModelAttribute instead of #RequesParam. When I'm using it, my app don't give a errors, but it also couldn't correctly put the "items" to this parameter.
Any ideas?
P.S. May be you know more better method of taking list of parameters from JSP page for using their values (like taking checked items)?
Your table is outside of the <form></form> so when submitting, it doesnt send anything.