How to pass inner objects in Thymeleaf by submit? - thymeleaf

I have a page in which there are the main object and list of subobjects. When filling values and submitting the form the main object returns valid values and the list of subobjects returns as null.
//html
<form method="POST" th:object="${main}" th:action="#{/submitPostAction}">
<div th:each="filter, _indx : *{subobjects}">
//Controller
#PostMapping("/submitPostAction")
public String actionSubmit(ModelMap model, MainObject mainObject){
mainObject.getSubObjects() // is null!
...
}

Related

Passing data from view to controller action(httpget) to another view to same controller action (httppost)

I'm trying to enable posting Comments from the view where I display a Forum Post by id. That's the model which my view receives:
#model PostViewModel
the Model has and "Id" property, which I send to a controller with javascript:
<script>
$("#target").click(function () {
$("#formPlace").load('#Url.Action("AddComment","Posts", new { postId = Model.Id })');
});
</script>
That's the controller action I send the "postId" to:
[HttpGet]
public ActionResult AddComment(int postId)
{
var comment = new CommentViewModel();
comment.PostId = postId;
return this.PartialView("_AddComment", comment);
}
This view returns a form in which the user has to fill the comment's content:
#model MvcTemplate.Web.ViewModels.Posts.CommentViewModel
<div>
#using (Html.BeginForm("AddComment", "Posts", FormMethod.Post))
{
<div>Enter your comment here:</div>
<div>
#Html.TextAreaFor(x => Model.Content)
</div>
<input type="submit" name="Submit" />
}
</div>
When the view receives the model its "PostId" is still correct = what I set it with the javascript. However after the user submits the form, the CommentViewModel which is sent to the controller has 0(default int value) for "PostId". This is the controller action:
[HttpPost]
public ActionResult AddComment(CommentViewModel viewModel)
{
// transfer the view model to db model and save;
}
Any idea how I can keep the correct PostId?
When you submit the form to the AddComment action method, the default model binder will try to bind the form field values to the properties of your CommentViewModel object. Your form has an input field for the Content property, but you do not have one for the PostId. So the browser will send the value of only form element with name Content.
If you want PostId, You need to keep the Post id value in the form. Since user does not need to see/edit this, you may keep this in a hidden input field in the form.
You can use the Html.HiddenFor helper method to generate the hidden field with the name and value for the corresponding property.
#using (Html.BeginForm("AddComment", "Posts", FormMethod.Post))
{
<div>Enter your comment here:</div>
<div>
#Html.TextAreaFor(x => Model.Content)
</div>
#Html.HiddenFor(s=>s.PostId)
<input type="submit" name="Submit" />
}
Or just a hidden input element markup (the helper ultimately generate this only)
<input type="hidden" name="PostId" value="#Model.PostId" />
You need to put hidden field with PostId value in your form. You are only posting content. Alternatively your post action AddComment should have url parameter postId, so form's action url will include postId.
You can set your PostId in a TempData and can get in subsequent post action in controller. If you want to get it from view you need to set it in a hidden field as suggested by Shyju.

MVC get data from dynamic field

I'm very new in MVC :(
I created a dynamic form by cloning a principal DIV element and its elements. The elements are combobox, textbox and a date textbox. When I create a new "clone", the DIV every member of itself has an incremental ID like tab_Container, tab_Container_1, text, text1, combo, combo1, etc... Now, I'm trying to get the values of each member in the Divs into the controller.
Googling I find something like this:
[HttpPost]
public ActionResult NewEntry(Model Entry)
{
Control myControl = new Control();
myControl.FindControl("Text0");
if (myControl != null)
{
/// apparently, find the control,here i wanna to get the value of each field !! ¿?
/// do i have to create a list[] ... exist something like Entry.Text0 = myControl.value?
}
else
{
Response.Write("Control not found");
}
return View(Entry);
}
Any suggestion? Is Control the best option? Do I have to do something else in Javascript code?
While it's normally better to have some sort of Model / ViewModel this situation is a bit different. MVC binds on the "Name" property of your form inputs.
So say for instance your razor syntax generates something like this:
<form>
<input type="text" name="input1" />
<input type="text" name="input2" />
<!-- etc etc etc -->
<input type="submit" value="submit" />
</form>
since this is dynamically generated and you don't have a model that would cleanly bind to this. You can use the FormCollection type as the parameter of your action. This gives you a collection of all items posted to the server that you could then loop through or peer into to get the properties that you want.
public ActionResult myAction(FormCollection collection)
{
var value = collection["input1"];
var value2 = collection["input2"];
return View();
}

Accessing Data attribute of html input control in MVC2 controller

I am submiiting a form from view which contains input field with specific data attribute
<form>
<input type="text" data-user="001" name="mytext" />
</form>
this from is submitted to a controller
[HttpPost]
public ActionResult Settings(FormCollection formValues)
{
//here i can access input control's value by its name like
string user= formValues["mytext"];
}
but how i can get value of data-user attribute in controller?
I do not think you can do it. You can access session variable from controller like this, however:
string strsetting1 = (string)HttpContext.Session["setting1"];
In your Global.asax.cs:
protected void session_start()
{
Session["setting1"] = "Y";
}

Html.Actionlink passing null values to controller

I have this method in my controller called "DirectorySearchController"
public ActionResult PersonDetails(FoundPerson person) //for some reason person is null here
{
DirectoryViewModel viewModel = new DirectoryViewModel();
viewModel.person = person;
return View(viewModel);
}
When I pass some parameters to it from the view using Html.Actionlink it returns a null value
<ul data-role="listview">
#if (ViewBag.Message == "NO RESULTS FOUND")
{
<li>#ViewBag.Message</li>
}
else
{
foreach (var employee in Model)
{
<li>
<div class="ui-grid-b">
<div class="ui-block-a" style="width:20%; vertical-align:middle"><img src="#employee.pictureURL" width="40px" height="40px"/></div>
<div class="ui-block-b" style="width:80%; vertical-align:middle">#Html.ActionLink(employee.name, "PersonDetails", "DirectorySearch", new { person = employee}, null)</div>
</div>
</li>
}
}
</ul>
But the funny thing is that when I pass the parameter without using the "new" keyword it passes the correct value. However, the problem is I need to pass multiple parameters so I need to use the "new" keyword.
<div class="ui-block-b" style="width:80%; vertical-align:middle">#Html.ActionLink(employee.name, "PersonDetails", "DirectorySearch", employee, null)</div>
I think you are not using the correct overload of ActionLink. Try with either of these
The first one should mostly work according to your case:
<%=Html.ActionLink(employee.Name, "PersonalDetails", "DirectorySearch", new { person = employee }, null)%>
<%=Html.ActionLink(employee.Name, "PersonalDetails", new {person = employee})%>
Just a recommendation here. Ideally I'd use an Input submit to post the data to the Controller. You may either use a Model class OR FormCollection in the controller side to retrieve the values you entered in the View.
You should not pass model to the controller action like new { person = employee } in Html.ActionLink. Because what happens is, when you generate the action link the object you pass is converted into RouteValueDictionary which will be passed to the UrlHelper to append the route dictionary values to the link.
When you pass an anonymous object like in the first case the RouteValueDictionary stores a single parameter with name person and to set the value it sees that you have passed an object, it can't serialize the complete instance and set it to the single property so all it does is set the type name of the model Employee as the value to the person. So you will see the generated link as http://someserver/DirectorySearch/PersonDetails?person=Models.Employee
If you pass an instance like you did in the second case then it iterate all the properties and create key/value pairs, while the keys are the property names and the values are the property values, finally they all appended to the link as querystrings. In the case the generated url will be http://someserver/DirectorySearch/PersonDetails?Property1=Value1&Property2=Value2
Correct
#Html.ActionLink(employee.name, "PersonDetails", "DirectorySearch", employee, null)
Wrong
#Html.ActionLink(employee.name, "PersonDetails", "DirectorySearch", new {person = employee }, null)
You can use anonymous object to pass route parameters to the action link but at the time you should not pass reference types but built-in types like integer, string..
Ex.
#Html.ActionLink(employee.name, "PersonDetails", "DirectorySearch",
new { Id = 23, Name = "Mark" }, null)

Posting an array of HTML.DropDownList values to controller action method

So in my view I am dynamically creating dropdown lists in a for loop. I use the same name value in unique id values.
#foreach(var item in Model.Items)
{
#Html.DropDownList("Items" Model.GenerateSelectList(item.id), new { id = item.id })
}
In my controller action method for the post I can get the values of the dropdowns like this:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public ActionResult ClassicLineup(IList<int> items)
{
}
I cannot figure out how to get BOTH the dropdown id and associated value.
Seems like it should be simple but it has me stumped...
Thanks.
On form submit browser sends only the selected value of a dropdown, so there is no bult in mechanism to read the text of selected item, but you can create one for you.
In below code i have created a hidden input which stores the text of current selected item, and is send to the server on form post.
You can create below list in controller or in view (preferred place in controller);
var items= (from item in Model.Items
select new SelectListItem
{
Value= item.DisplayProperty
Text= item.Value
}).toList();
<form action="controller/test">
#*This will create DD*#
#Html.DropDownList("MyDropDownList", items)
#*Hidden input*#
<input type="hidden" id="ddSelectedName" name="ddSelectedName" />
<br>
<input type="submit" value="submit"/>
</form>
Include jQuery in ur code and then add this
<script type="text/javascript">
$('#MyDropDownList').change(function () {
$('#ddSelectedName').val($(this).find(':selected').text());
});
</script>
Controller
public string test(string MyDropDownList, string ddSelectedName)
{
return MyDropDownList+ "--"+ddSelectedName ;
}
I just ended up looping through the forms collection and parsing the dropdown id (form.key) and the dropdown value (form.key.value).
Apparently there is not an easy way to have MVC bind the dropdown values and id to a collection in the controller action parameter.

Resources