Versions :
Aapche MyFaces 2.1.14
RichFaces 4.3.5
Issue :
I have a class implementing map interface like below :
public class FormStore implements Map {
private Map values;
public Object get(Object key) {
return values.get(key);
}
public Object put(Object key, Object value) {
return values.put(key, value);
}
}
I am using this map to store all submitted form values in my application and accessing in facelet as shown in below facelet code :
<h:inputText id="phone" value="#{formStore['phone']}" size="12" maxlength="20" required="true">
where formStore is the java class above.
Now I have added another Map in above java class as below which serves some special purpose.
public class FormStore implements Map {
private Map values;
private Map additionalValues;
public Object get(Object key) {
return values.get(key);
}
public Object put(Object key, Object value) {
return values.put(key, value);
}
//getter and setter method for additionalValues also added
}
The issue is I am not able to access this new map from EL . I have tried following options :
1)<h:inputText id="phone" value="#{formStore.additionalValues['phone']}" size="12" maxlength="20" required="true">
2)<h:inputText id="phone" value="#{formStore.[additionalValues]['phone']}" size="12" maxlength="20" required="true">
3)<h:inputText id="phone" value="#{formStore[additionalValues]['phone']}" size="12" maxlength="20" required="true">
For every option , it calls FormStore.get method with key = additionalValues
Is it not possible to access the additionalValues map from FormStore.java class ?
Please help.
This should work
<h:inputText id="phone" value="#{formStore.getAdditionalValues()['phone']}" size="12" maxlength="20" required="true">
Related
I have a jsp form with an input box, a domain object with get/set methods, and a controller. When I submit the form I get null values in the controller. The "set" method is never being called in the domain object when i submit the form but the object itself is being called.
Order.jsp
<portlet:defineObjects />
<portlet:actionURL portletMode="view" var="createNewOrderURL">
<portlet:param name="action" value="createNewOrder" />
</portlet:actionURL>
<div>
<form:form name="form" method="post" commandName="refOrder" action="${createNewOrderURL}" id="createOrder">
TestName : ${refOrder.name}<br/> <!-- here I get the correct value to display -->
<form:input path="referenceNum" />
<input type="submit" value="Submit" />
</form:form>
</div>
Order.java
public class Order {
private String name = "Name1";
private String referenceNum;
public Order(){
System.out.println("Inside Order.java");
System.out.println(getReferenceNum());
}
public Order(String name, String referenceNum) {
this.name = name;
this.referenceNum = referenceNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getReferenceNum() {
return referenceNum;
}
public void setReferenceNum(String referenceNum) {
this.referenceNum = referenceNum;
}
SalesOrderController.java
#RenderMapping
public String defaultRender(RenderRequest request, RenderResponse response, Model model) throws SQLException, NamingException{
model.addAttribute("refOrder",new Order());
return "SalesOrderEntry";
}
#ActionMapping(params={"action=createNewOrder"})
public void addNewOrder(ActionRequest request, ActionResponse response, #ModelAttribute("refOrder") Order order)throws NamingException, SQLException{
System.out.println("Inside addNewOrder method");
System.out.println("New Order is --> "+order.toString());
System.out.println("RefNum - "+order.getReferenceNum());
System.out.println("request.getParameter is "+request.getParameter("referenceNum"));
}
I get null for all the print statements in the controller. Have been trying to fix this for two days now and I can't find what's wrong. Would really appreciate if someone can help me get this to work.
Do you have the following in your src/main/webapp/WEB-INF/liferay-portlet.xml descriptor?
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Also, you might want to take a look at the PortletMVC4Spring project, which is the successor to Spring Portlet MVC. The GitHub project contains archetypes that work in Apache Pluto and Liferay Portal. The requires-namespaced-parameters config option is conveniently set in the archetypes.
I have a form in a razor page with a field that has remote validation..
. . .
<div class="form-group">
<label class="control-label" asp-for="ReportViewModel.ExecSql"></label>
<textarea class="form-control" asp-for="ReportViewModel.ExecSql" ></textarea>
<span asp-validation-for="ReportViewModel.ExecSql" class="text-danger"></span>
</div>
. . .
The field in the ReportViewModel is defined as:
. . .
[Remote(action: "VerifySql", controller: "ReportService", HttpMethod = "POST")]
public string ExecSql { get; set; }
To call the action below:
[AcceptVerbs("Post")]
public IActionResult VerifySql(string ExecSql)
{
if (!Repository.VerifySql(ExecSql))
return Json("Sql is not valid (Select statements only are allowed)");
return Json(data: true);
}
The razor page cs file:
public class AddReportModel : PageModel
{
private readonly IIntegrityReportRepository _repository;
private readonly IMapper _mapper;
public AddReportModel(IIntegrityReportRepository repository, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}
[TempData]
public string ConfirmationMessage { get; set; }
[BindProperty]
public IntegrityReportViewModel ReportViewModel { get; set; }
. . .
This calls the action but ExecSql is always null. This is because when I look at the request, the form is posting.. ReportViewModel.ExecSql. Which I cannot pick up from my VerifySql action method.
I have tried adding a name to the cshtml field:
<textarea class="form-control" asp-for="ReportViewModel.ExecSql" name="ExecSql" ></textarea>
This then does bind the field and pass the value, however the client side validation does not work when it is passed back.
I can get it working by defining ANOTHER field in the cs razor page file e.g.
[Remote(action: "VerifySql", controller: "ReportService", HttpMethod = "POST")]
[BindProperty]
public string ExecSqlField { get; set; }
And then changing the cshtml to:
<div class="form-group">
<label class="control-label" asp-for="ExecSqlField"></label>
<textarea class="form-control" asp-for="ExecSqlField"></textarea>
<span asp-validation-for="ExecSqlField" class="text-danger"></span>
</div>
However this feels wrong and I am then duplicating the viewmodel which I need to share across another pages. Is there anyway to pick up the field in the original viewmodel in my action method by somehow getting the Verify action method to access ReportViewModel.ExecSql?
Many thanks for any help
Just wanted to add that #Baseless and #Breno did have the correct answer.
My property was as such:
[Display(Name = "Access Code")]
[Remote("CheckForGroup", "Users", "Admin", HttpMethod = "Post")]
public string AccessCode { get; set; }
and it only worked when I added this to my controller:
public IActionResult CheckForGroup([Bind(Prefix = "Input.AccessCode")] string accessCode)
Thank you guys!
Afte banging heads a lot, I found a workaround. Not the most elegant but it is doing the job right now.
Just add [Bind(Prefix = "ReportViewModel.ExecSql")] to your validation method parameter.
You can revert the changes and resume using the "Model.Field" form pattern.
I have the following code in my view
<input class="form-control" type="text" name="dev" value="foobar" />
In the controller I have
public ActionResult BobLobLaw(string dev)
The above works well. But then I changed my view model, now my view code becomes like
<input class="form-control" type="text" name="arrested.dev" value="foobar" />
How should I name my action param so that it will bind to the new input name ("arrested.dev") ?
Additionally, looking on how to do this for enum type as well. e.g.
<% Html.DropDownList("arrested.devEnum", SelectList) %>
public ActionResult BobLobLaw2(suitEnum arrested.devEnum)
The modelbinder interprets a . to mean a property on an object. So you would need some object with a property of dev as a parameter:
public class Arrested
{
public string dev { get; set; }
}
Then:
public ActionResult BobLobLaw(Arrested arrested)
{
...
}
I have a form object
public class TestForm {
private long id;
private List<Date> dates;
// getters and setters for the above
}
And my controller has the following..
#RequestMapping(value = "/assignDummy", method = RequestMethod.POST)
public #ResponseBody
String assignDates(TestForm frm) {
System.out.println("frm:"+frm.getId()+", date:"+frm.getDates());
return "Everything is fine";
}
My form..
<form name="abc" method="post" action="assignDummy.htm">
<input type="text" name="id" value="1000">
<input type="text" name="dates[0]" value="4500000">
<input type="submit">
</form>
I get the following error..
Failed to convert property value of type 'java.lang.String' to
required type 'java.util.Date' for property 'dates[0]'; nested
exception is
org.springframework.core.convert.ConversionFailedException: Failed to
convert from type java.lang.String to type java.util.Date for value
'4500000'; nested exception is java.lang.IllegalArgumentException"
Any help is appreciated.
Thanks in advance
You are trying to put a String into Date without converting it, so it crashes.
You have to use a custom property editor in order to convert the input String into a Date.
Try to add in your controller
#InitBinder
public void initBinder(WebDataBinder binder) {
CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"), true);
binder.registerCustomEditor(Date.class, editor);
}
I want to use the form:options provided by Spring to provide choices.
My JSP implemented with Spring 2.5 is
<td><form:select path="billingType">
<form:options items="${addAccountCommand.billingTypeChoice}" itemValue="billingType" itemLabel="billingTypeName" />
</form:select>
</td>
My AccountCommand.java is
private int billingType;
private String billingTypeName;
public int getBillingType() {
return billingType;
}
public void setBillingType(int billingType) {
this.billingType = billingType;
}
private Map<String, Integer> billingTypeChoice = new HashMap<String, Integer>() {
{
put("Monthly", 1);
put("Block", 2);
put("Per Use", 3);
}
};
public Map<String, Integer> getbillingTypeChoice() {
return billingTypeChoice;
}
public void setbillingTypeChoice(Map<String, Integer> billingTypeChoice) {
this.billingTypeChoice = billingTypeChoice;
}
public String getBillingTypeName() {
return billingTypeName;
}
public void setBillingTypeName(String billingTypeName) {
this.billingTypeName = billingTypeName;
}
My Eclipse console is:
15:55:23,140 ERROR org.springframework.web.servlet.tags.form.OptionsTag:84 - Invalid property 'billingType' of bean class [java.lang.String]: Bean property 'billingType' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
org.springframework.beans.NotReadablePropertyException: Invalid property 'billingType' of bean class [java.lang.String]: Bean property 'billingType' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:540)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:532)
at org.springframework.web.servlet.tags.form.OptionWriter.renderFromMap(OptionWriter.java:164)
...
When you do:
<form:options items="${addAccountCommand.billingTypeChoice}" itemValue="billingType" itemLabel="billingTypeName" />
you are saying go to addAccountCommand.billingTypeChoice which is a Map and do a getBillingType() for the value and a getBillingTypeName() for the label. As these methods are not defined on the map you get the error. You should use getKey() and getValue() on the map.As you have it defined now it should be:
<form:options items="${addAccountCommand.billingTypeChoice}" itemValue="key" itemLabel="value" />
because you have defined the Map in a very strange way. It's usually Map because I suppose the key is the Integer and the value the String.
Hope it helps.
I just tried it on Spring 2.5. Just code below should work.
<form:select path="billingType">
<form:options items="${addAccountCommand.billingTypeChoice}" />
</form:select>