I know that in the html helper BeginForm available in asp.net mvc there is a param called htmlAttributes. How can I use it witouth specify the previous params? I don't want to override the default action/method values
You could do something like this:
#using(Html.BeginForm(ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), FormMethod.Post, new{title = "title"}))
{
...
}
which outputs:
<form action="/" class="someclass" method="post">
</form>
It's not exaclty what you wanted and it's not pretty. You do have to specify the FormMethod.
Or add the attributes you need via jQuery.
Passing null as the value of the BeginForm function will apply the default params value
Related
I have simple web application written using Springboot and Thymeleaf templates. Report controller receives the data from form and builds the TestPlanReportResponse object which is added as model attribute like this:
#PostMapping("/report")
public String homeSubmit(#ModelAttribute HomeFormInput homeFormInput, Model model, Errors errors) {
final TestPlanReportResponse response = new TestPlanReportResponse(homeFormInput);
model.addAttribute("allData", response);
return "charts";
}
I can work with that data in "charts" thymeleaf template and show the data I need, but I need to send exactly the same object back to controller when button is clicked, but i getting TestPlanReportResponse
object as parameter with nulls set.
#PostMapping("/report/send")
public String sendReport(#ModelAttribute TestPlanReportResponse reportData, Model model) {
//reportData contains just nulls
}
Here is how my button is set in charts template:
<form action="#" th:action="#{/report/send}" th:object="${allData}" method="post">
<button type="submit">Send the report</button>
</form>
So my question is how to send the object back from thymeleaf template? Should i create a hidden input and put there the "allData" object just to send it back? It looks for me like dirty hack. What would be the appropriate way to pass data back? I want to have this app stateless so don't to store the data on a server side.
When I used to work with Spring and Thymeleaf and form, we had the same issue, passing the data back and forth between a form, the template, and different controllers.
And what you suggest is what we did, we used hidden input as dirty as it may look,it was the standard suggested answer, we did not find anything better.
You need to create an input, with a type a value and link it to a field, like this:
<form action="#" th:action="#{/report/send}" th:object="${allData}" method="post">
<input type="hidden" th:value="*{allDataValue1}" th:field="*{allDataField1}" />
//Do this for all your attributes/values that you wish to pass to the controller
<button class="btn btn-info btn-lg btn-block" type="submit">Send the report</button>
</form>
Though, i found this answer, you can try looking into this thread
I'm trying to add an attribute to an HTTP session with thyme leaf, but I can't. I had a "Project" object and I need to pass it to the controller. I had a form in the page, so I've tried this, but it doesn't work:
<input type="hidden" th:attr="${#session.setAttribute('proyecto', '${proyecto}')}"
The controller receives the attribute proyecto but the value is "${proyecto}", not the content of the project object
Send the value using a form and then set the session attribute in your controller.
HTML
<form th:action="#{/newProject}" th:object="${newProject}" method="post">
<input th:field="*{id}"></input>
</form>
Controller
#RequestMapping(value = "/newProject", method = RequestMethod.POST)
public String addProject(HttpSession session, #ModelAttribute("newProject") Project project) {
session.setAttribute("proyecto", project);
return "/newPage";
}
This is just example of course. You would need to add all the project fields in your HTML.
I have a project developed with tapestry 5.
I need to update a input field (which is inside a form) using an AJAX request.
Page.tml is something like this:
<form>
<t:zone t:id="myZone">
<input type="text" t:type="TextField" t:value="product.code"/>
</t:zone>
<t:actionlink t:id="generateCode" zone="myZone">Generate</t:actionlink>
</form>
And Page.java
Object onActionFromGenerateCode() {
return myZone.body();
}
When click in "Generate" link, tapestry throws an exception. Don't let me update a zone inside a form:
java.lang.RuntimeException
The component must be enclosed by a Form component.
How can I update this input field?
thanks
Changing pieces of a form via ajax gets tricky as a FormSupport instance must be available on the Environment in the serverside event.
It might be easier to either:
Put the entire form in a zone and refresh the whole form
Execute some javascript from the serverside event
Here's how option 2 could work:
TML
<form>
<input id="productCode" type="text" t:type="TextField" t:value="product.code" />
<!-- note that async is a recent addition to eventlink in tapestry 5.4 -->
<!-- Use a dummy zone for previous versions -->
<t:eventlink event="generateCode" async="true">Generate</t:eventlink>
</form>
Java
#Inject JavaScriptSupport jss
void onGenerateCode() {
String productCode = generateProductCode();
jss.addScript("$('#productCode').val('%s');", productCode); // assuming jquery
}
Note, it is possible to dynamically change a form via ajax, it's just tricky as I said. Examples include AjaxFormLoop and the FormInjector
What is the defined behavior for form binding in ASP.NET/MVC if you POST a form and its action has query parameters and you have form data?
For example:
<form action="my/action?foo=1" method="post">
<input type="hidden" name="bar" value="2">
</form>
If such a form is submitted should the controller get both foo and bar or only one of them?
The controller will get both values. The default model binder will try to find matches for the parameters from both the URI (either query string or route parameters) or the body (and forms data is supported out-of-the-box).
Note, you can see this is supported by Html.BeginForm helper, you do so through routeValues:
#Html.BeginForm("ActionName", "ControllerName", new { foo = "1" })
It essentially generates the same html as your form tag, but wanted to post for those who find this question and want to know how to pass additional values that are not part of the form using the BeginForm helper.
I think it should be able to get both. In this case, I would create a ViewModel that contains two string or int properties, one named 'foo' and the other named' bar' and have your ActionResult accept the ViewModel. You should see both values come in.
Lets say I have...
#Html.EditorFor(i => i.Date)
... and I have a template defined for items of type DateTime. In my template I have...
<input type="text" name="???" />
Given that the template only receives a DateTime instance, how can one have the template dynamically generate the name of the form field based on the original Model property name being assigned to the template?
Otherwise, upon post back, the model binder won't be able to match up the value from the template with the 'Date' property assigned to it!
Cheers, Ian.
You could in turn use a Html.TextBox instead of writing out the input tag yourself and it would handle it for you:
#Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new {#class = "date"})
Leave the name empty and it will automatically get populated for you. If you want to explicitly write out the HTML tags yourself though, I think that you can get the name with this:
<input type="text" name="#ViewData.ModelMetadata.DataTypeName" />