I need to access the data being input through the Magnolia script template, from the Magnolia Java model.
I have tried setting up parameters and definitions. I have tried using different properties of the definition and content Node.
public FormModel(Node content, ConfiguredTemplateDefinition definition, RenderingModel<?> parent) {
super(content, definition, parent);
}
public String execute() {
HttpServletRequest request = MgnlContext.getWebContext().getRequest();
if ("POST".equals(request.getMethod())) {
try {
//Access the name input from the template script
}
catch(Exception e) {
System.out.print(e);
}
}
return super.execute();
}
}
<form method="post">
<div>
<label>Name:</label>
<input type="text" name="name"/>
</div>
</form>
I want to be able to access the value of input in the Java code.
You need to specify the modelClass attribute in your template definition, and FormModel should extend info.magnolia.rendering.model.RenderingModelImpl<>. You didn't specify if you did any of these, so it's very hard to guess what might be wrong there.
If you're using YAML, the definition should look like this:
renderType: freemarker
templateScript: /my-module/templates/components/home.ftl
modelClass: my.awesome.FormModel
Related
I have an enum like this
public enum CheckboxFeature {
Option1(" choose this"),
Option2(" or this"),
Option3(" maybe this"),
Option4(" lastly this");
#Getter
private final String text;
public static CheckboxFeature fromName(String v) {
for (CheckboxFeature c: CheckboxFeature.values()) {
if (c.name().equalsIgnoreCase(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
This shows the four options as checkboxes in the web view
<form:checkboxes items="${features}" path="enabledFeatures" itemLabel="text" delimiter="<br/>"/>
How can I translate these options? I use fmt:message for the rest of the translations in the web view.
I have tried
Option1(" <fmt:message key=\"text.test\"/>"),
and
Option1(" ${option1}"),
with
<fmt:message key="text.select" var="option1"/>
in the .jsp.
Neither of them work, so it seems it can't work this way. What is the correct way of translating the strings? Ideally using the fmt:message and i18n resources (lang.properties files) that are in place and working on the rest of the servlet?
Optimally, you get the resource key from the enum, and look that up.
public enum CheckboxFeature {
Option1("label.option1.key"),
Option2("label.option2.key"),
Option1("label.option3.key"),
Option2("label.option4.key");
private final String key;
[...]
I don't know how to nest a l10n lookup in the itemLabel attribute, so I would write something like:
<c:forEach items="Options.values()" var="current">
<form:checkbox path="selectedOptions" value="${current.name()}"/> <fmt:message key="${current.getKey()}"/>
</c:forEach>
1、CheckboxFeature add method like:
public static List<String> getAllCheckboxFeature(String v) {
return Arrays.asList(Option1.getText(),...Option4.getText());
}
2、than use the jstl like:
<c:forEach items="${options}" var="option">
<input type="checkbox" ="${option}">
</c:forEach>
I have some Java REST ws handling POST data from a simple HTML form.
I want to make the client code send to the ws the right JSON to make the server code populate my objects the right way.
I have the following data structure:
public class CarDTO
{
String id;
String defaultName;
List<CarCategoryDTO> carCategoryDTOs;
List<CarTranslationsDTO> carTranslationsDTOs;
/* getter, setter, constructors*/
}
public class CarCategoryDTO
{
String id;
String defaultName;
/* getter, setter, constructors*/
}
public class CarTranslationsDTO
{
int id;
String name;
LanguageDTO languageDTO;
/* getter, setter, constructors*/
}
public class LanguageDTO
{
String code;
/* getter, setter, constructors*/
}
POST Action:
#POST
#Path("/save")
public Response saveCar(String args)
{
try
{
Gson g = new GsonBuilder().create();
CarDTO carDTO = g.fromJson(args, CarDTO.class);
System.out.println(carDTO);
return Response.ok(g.toJson(carDTO)).build();
} catch (Exception e) {
e.printStackTrace();
return Response.serverError().build();
}
}
Client code:
<form id="form_car"
enctype="application/json"
action="http://www.someurl.com:8080/rest/0.1/car/save"
method="POST">
<input type="text" name="defaultName" />
<input type="hidden" name="carTranslationsDTOs[0][languageDTO][code]" value='en'>
<input type="text" name="carTranslationsDTOs[0][name]">
<input type="text" name="carCategoryDTOs[0][defaultName]" value="cat1">
<input id="submitbutton" type="button" value="Salva"/>
</form>
<script>
jQuery("#submitbutton").click(function(){
var formData = JSON.stringify(jQuery("#form_car").serializeObject());
jQuery.ajax({
url: "http://www.someurl.com:8080/rest/0.1/car/save",
type:"POST",
data:formData,
contentType:"application/json; charset=utf-8",
dataType:"json",
success: function(data){
console.log(data);
}
});
});
</script>
I also added the following jQuery extension, but it wasn't enough: jquery.serializeObject.js
The problem is the mapping with Collection of parameters, the result is that I can populate only CarDTO.id and CarDTO.defaultName.
How can I make it work?
EDIT 25/03/2015:
I figured up that the simplest way to solve my problem is to make the json manually from javascript at the submit, tough this don't satisfy me because a lot of the logic is client side, and exposing all my DTO structures in this way is awful.
I didn't know of any custom deserialization in Gson, I think that's the right path to follow.
Any other help and different opinions are well accepted.
You'll likely need to process the JSON until it's in a form that Gson can recognize, i.e. something along the lines of:
{
"defaultName": "Ford",
"carCategoryDTOs": [{
"defaultName": "cat1"
}],
"carTranslationsDTOs": [{
"name": "Ford",
"languageDTO": {
"code": "en"
}
}]
}
If you still run into issues, you may need to write a custom deserializer, see the Writing a Deserializer section of the Gson User Guide.
Note that you're naming conventions for your carTranslationsDTOs is off. Since it's already a has_many relationship, and each carTranslationsDTOs is actually a single translation, this should be named carTranslationDTOs according to your convention.
Your JSON doesn't map to your data structure; the following is the result JSON using your code:
{
"defaultName":"default car name",
"carTranslationsDTOs[0][languageDTO][code]":"en",
"carTranslationsDTOs[0][name]":"car name in en",
"carCategoryDTOs[0][defaultName]":"cat1"
}
While GSON expects something like
{
"defaultName":"default car name",
"carCategoryDTOs":[{"defaultName":"cat1"}],
"carTranslationsDTOs":[{"name":"car name in en",languageDTO:{"code":"en"}}],
}
I wrote a jQuery plugin that serializes/deserializes flat and nested html form data to / from javascript / json. I haven't tried in your particular case but as far as I can see it might solve the problem.
Just have a look at https://github.com/omanshardt/jquery-uicForm3.git.
I am using plain HTML checkbox(not Tapestry type). I need to set the checkbox to checked in my java page. How do I do that?
Here is my tml code fragment
<input type="checkbox" name="leaf" id="leaf" value="leaf"/>
Any help would be appreciated. Thanks.
You need to set the checked property. I'd probably use the <t:any> component.
TML
<t:any element="input" type="literal:checkbox" name="literal:leaf" id="prop:clientId" value="prop:currentObject.value" checked="prop:checked" />
JAVA
#Property
private SomeType currentObject;
public String getClientId() {
return "mycheckbox_" + currentObject.getId();
}
// if this returns null, tapestry won't render the attribute
public String getChecked() {
return currentObject.isSelected() ? "checked" : null;
}
I've been having trouble getting my Form bindings to work properly(basically Trial and Error).
In Play 2.0.3 (Java) What is the proper way to bind a Form to a Model which is composed of other objects ?
I cooked up this little example to try and understand it better.
But even this basic example seems to have issues.
The Simple class which I'm trying to bind the Form to has 3 fields a plain String Field,A List of Strings and a custom field which is just a wrapper around a string.
On submitting the Form all the fields are populated except the custom field which remains null.
Here's the actual code
Controller
static Form<Simple> simpleform=form(Simple.class);
public static Result simpleForm(){
Form<Simple> filledForm=simpleform.bindFromRequest();
System.out.println(filledForm);
return ok(views.html.simpleForm.render(filledForm.get().toString()));
}
Model
public class Simple {
public String text;
public List<String> stringList;
public SimpleWrapper wrappedText;
#Override
public String toString(){
return text +"-"+simpleWrapper+"-"+stringList;
}
public class SimpleWrapper{
String otherText;
public SimpleWrapper(){}
public SimpleWrapper(String otherText){
this.otherText=otherText;
}
#Override
public String toString(){
return otherText;
}
}
View
#(text:String)
#import helper._
#form(routes.Management.simpleForm()){
<input type="hidden" value="string" name="stringList[0]">
<input type="hidden" value="stringAgain" name="stringList[1]">
<input type="hidden" value="wrapped" name="wrappedText.otherText">
<input type="text" id="text" name="text">
<input type="submit" value="submit">
}
This was passed #text
To allow for automatic binding of objects you must supply a setter method for your class.In my experiment the SimpleWrapper class was missing the setter method the class should have been
public class SimpleWrapper{
String otherText;
public SimpleWrapper(){}
public setOtherText(String otherText){
this.otherText=otherText;
}
#Override
public String toString(){
return otherText;
}
}
It appears even the constructor is irrelevant.
This is a link about the underlying Spring data binder link that might be helpful. I got that from the play google group
I'm using Spring 3.1.0.RELEASE. I have this field in my command object ...
public Set<EventFeed> getUserEventFeeds() {
return this.userEventFeeds;
}
On my Spring JSP page, I want to display a checkbox list of all possible event feeds, and then have checked checkboxes if the user has one in his set. I want to have some special HTML formatting around each checkbox, so I'm trying ...
<form:form method="Post" action="eventfeeds.jsp" commandName="user">
...
<c:forEach var="eventFeed" items="${eventFeeds}">
<tr>
<td><form:checkbox path="userEventFeeds" value="${eventFeed}"/></td>
<td>${eventFeed.title}</td>
</tr>
</c:forEach>
...
However, the items aren't getting checked by default if one is in the set. How do I do this? Here is the binder I'm using in my controller class ...
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(EventFeed.class, new EventFeedEditor());
}
private class EventFeedEditor extends PropertyEditorSupport {
#Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(eventFeedsDao.findById(Integer.valueOf(text)));
}
#Override
public String getAsText() {
return ((EventFeed) getValue()).getId().toString();
}
}
#Dave, there is something called form:checkBoxes. You can try with that.
<form:checkboxes path="userEventFeeds" items="${eventFeeds}" itemLabel="id" itemValue="value"/>
My assumption here is you should have "id" and "value" defined in the EventFeed class.
I just tried this by having a String[] availableList and String[] selectedList. It works like charm. You can give a try as well.
Interestingly this works:
<form:checkbox path="services" value="${type}" checked="checked"/>
You can do this by placing selected default property true in your class
class User {
boolean userEventFeeds = true;
}
I've tried both form:checkboxes and form:checkbox with the same data and the first works, the second doesn't. (Same release of Spring you have)
It looks like there was a bug which, despite their claim, seems to be still there.
For my usecase (reacting on stuff in a list that has nothing to do with the object being filled), this code worked:
(Please be aware that this is a last-resort kind of code, other solutions are most likely better suited.)
<%# taglib prefix="jstl" uri="http://java.sun.com/jsp/jstl/core" %>
<jstl:forEach var="listObject" items="${someList}">
<jstl:if test="${listObject.active}">
<form:checkbox path="active" checked="checked"/>
</jstl:if>
<jstl:if test="${!listObject.active}">
<form:checkbox path="active"/>
</jstl:if>
</jstl:forEach>