Thymeleaf, how to make th:name like this? - thymeleaf

For this to work I neeed th:name to be dishIdQuantityMap[dish.id] ( for example, if dish has an id of 1 - dishIdQuantityMap[1];
But how can this be implemented?
<div class="single-menu" th:each="dish : ${dishList}">
<form action="#" th:action="#{/menu}" th:object="${order}" method="post">
<input
th:value="0"
th:name="!!!!"
type="number"
min="0"
max="100"
step="1"
/>
</form>
</div>
Here is an example of OrderDto.
public class OrderDto {
private Map<Long, Integer> dishIdQuantityMap;
}

Standard expression syntax.
th:name="|dishIdQuantityMap[${dish.id}]|"
or
th:name="${'dishIdQuantityMap[' + dish.id + ']'}"

Related

input-validation-error added to input incorrectly

Why is the input-validation-error class being added to my input when it shouldn't?
Validation is working fine for other pages that actually use it. I've tried making the property nullable and using the ValidateNever attribute but both are ignored.
View Model
public class EntityTableViewModel
{
[ValidateNever]
public string? SearchTerm { get; set; }
}
HTML
<form method="get">
<div class="input-group">
<input asp-for="SearchTerm" type="search" class="form-control rounded" placeholder="Search" />
<button type="submit" class="btn btn-primary" asp-action="Index"><i class="bi bi-search"></i></button>
</div>
</form>
Rendered HTML
<input type="search" class="form-control rounded input-validation-error" placeholder="Search" id="SearchTerm" name="SearchTerm" value="">

How to model bind dynamic radio buttons in ASP.net Core / 5

I have a Likert Survey generator where a dynamic number of questions can be entered - then a user goes through and answers each question with 4 radio buttons (Strongly Disagree, Disagree, Agree, Strongly Agree).
I can output them easily enough - but can they be model bound on the post back or do I have to traverse the posted form elements (ie not use model binding)?
I've Googled a lot and can find no solution - is it posible?
Thanks.
If you want to bind a list in view,here is a demo about binding a list with input names:
Model:
public class Qusetion
{
public string Content { get; set; }
public string Answer { get; set; }
}
View:
<form method="post">
<div>
<label>question1</label>
<input name="list[0].Content" value="question1" hidden/>
<div>
<input type="radio" name="list[0].Answer" value="Strongly Disagree" />Strongly Disagree
<input type="radio" name="list[0].Answer" value="Disagree" />Disagree
<input type="radio" name="list[0].Answer" value="Agree" />Agree
<input type="radio" name="list[0].Answer" value="Strongly Agree" />Strongly Agree
</div>
</div>
<div>
<label>question2</label>
<input name="list[1].Content" value="question2" hidden/>
<div>
<input type="radio" name="list[1].Answer" value="Strongly Disagree" />Strongly Disagree
<input type="radio" name="list[1].Answer" value="Disagree" />Disagree
<input type="radio" name="list[1].Answer" value="Agree" />Agree
<input type="radio" name="list[1].Answer" value="Strongly Agree" />Strongly Agree
</div>
</div>
<div>
<label>question3</label>
<input name="list[2].Content" value="question3" hidden/>
<div>
<input type="radio" name="list[2].Answer" value="Strongly Disagree" />Strongly Disagree
<input type="radio" name="list[2].Answer" value="Disagree" />Disagree
<input type="radio" name="list[2].Answer" value="Agree" />Agree
<input type="radio" name="list[2].Answer" value="Strongly Agree" />Strongly Agree
</div>
</div>
<input type="submit" value="submit" />
</form>
Controller:
public IActionResult BindList(List<Qusetion> list)
{
return View();
}
result:
Update:
If you want to bind with loop.you can pass list to view.And the code will work is because .net core bind model with name attribute.And because you want to bind list,so the name will be like list[index].xxx.
Here is a demo with loop:
View:
#model IEnumerable<Qusetion>
<form method="post">
#{ var i = 0;}
#foreach (var question in Model)
{
<div>
<label>#question.Content</label>
<input name="list[#i].Content" value="#question.Content" hidden />
<div>
<input type="radio" name="list[#i].Answer" value="Strongly Disagree" />Strongly Disagree
<input type="radio" name="list[#i].Answer" value="Disagree" />Disagree
<input type="radio" name="list[#i].Answer" value="Agree" />Agree
<input type="radio" name="list[#i].Answer" value="Strongly Agree" />Strongly Agree
</div>
</div>
i++;
}
<input type="submit" value="submit" />
</form>
Controller:
public IActionResult BindList(List<Qusetion> list)
{
List<Qusetion> list1 = new List<Qusetion> { new Qusetion { Content = "question1" }, new Qusetion { Content = "question2" }, new Qusetion { Content = "question3" } };
return View(list1);
}
result:

how to bind list of ids to command object in grails?

Let's say when you submit a form it sends a list of ids.
<form action="/process">
<input type="hidden" name="ids" value="4, 6, 10, 14, 20, 56" >
<input type="submit" value="Submit">
</form>
At the controller side
def process(EmailCommand cmd){
//now iterating over registrations after data binding
cmd.ids.each {
}
}
//Command Object
class EmailCommand {
List<Registration> ids
}
I want to bind all the ids passed to controller to the ids list in EmailCommand command object. How can i achieve it? I appreciate any help! Thanks!
It would be something like
<form action="/process">
<input type="hidden" name="ids[0].id" value="4" >
<input type="hidden" name="ids[1].id" value="6" >
<input type="hidden" name="ids[2].id" value="10" >
<input type="hidden" name="ids[3].id" value="14" >
<input type="hidden" name="ids[4].id" value="20" >
<input type="hidden" name="ids[5].id" value="56" >
<input type="submit" value="Submit">
</form>
Or if you want something more dynamic :
<form action="/process">
<g:each in="[4, 6, 10, 14, 20, 56]" var="id" status="i">
<input type="hidden" name="ids[${i}]" value="${id}" >
</g:each>
<input type="submit" value="Submit">
</form>
I could only get it to work after changing the command object to
class EmailCommand{
List<Registration> ids= ListUtils.lazyList([], { new Registration() } as Factory )
}
and view to the following as bassmartin suggested.
<g:hiddenField name="ids[0].id" value="1"></g:hiddenField>
<g:hiddenField name="ids[1].id" value="2"></g:hiddenField>
<g:hiddenField name="ids[2].id" value="3"></g:hiddenField>
<g:hiddenField name="ids[3].id" value="4"></g:hiddenField>
<g:hiddenField name="ids[4].id" value="5"></g:hiddenField>
<g:submitButton name="submit" value="submit"></g:submitButton>
I am wondering why empty list in command object doesn't work. Is this limitation of grails version 2.2?
You have 2 options here:
Straight forward -> trick with the split comma-separated String in the "setter":
class EmailCommand {
List<Registration> ids
void setIds( String val ){ ids = Registration.getAll( val.split( ', ' ) ) }
}
Correct -> use form params for that:
<form action="/process">
<g:each in="[4, 6, 10, 14, 20, 56]" var="id">
<input type="hidden" name="ids" value="${id}" >
</g:each>
<input type="submit" value="Submit">
</form>
and let grails do the binding.

Asp.Net MVC - Data permutator

I have searched for hours for this without finding an answer, so I'm asking your help (I'm a beginner in web development (and in Asp.Net MVC)).
I want to create a simple data permutator (for example you enter 3 datas "a, b, and c", and I give you the possible permutations between these 3 datas : "abc; acb; bac; bca; cab; cba").
I have tried the following code, but it does not work (I have an HTTP 404 error).
<form method="post">
<div class="col-md-4 input-group">
<div class="input-group-addon">1</div>
<input type="text" name="firstData" class="form-control" placeholder="First Data" maxlength="50" required />
</div>
<div class="col-md-4 input-group">
<div class="input-group-addon">2</div>
<input type="text" name="secondData" class="form-control" placeholder="Second Data" maxlength="50" required />
</div>
<div class="col-md-4 input-group">
<div class="input-group-addon">3</div>
<input type="text" name="thirdData" class="form-control" placeholder="Third Data" maxlength="50" required />
</div>
<div class="col-md-12 mainAction centerbloc">
<input type="submit" value="Permutate the data" class="btn btn-success register-button-slider" href="">
</div>
</form>
And then below, I want to display the result in the same page, like this :
#{ if (IsPost)
{
string firstdata = Request.Form["firstData"];
string seconddata = Request.Form["secondData"];
string thirddata = Request.Form["thirdData"];
<p>
#firstdata #seconddata #thirddata<br />
#seconddata #firstdata #thirddata<br />
</p>
}
}
I haven't put anything special in my controller (maybe the mistake is here?) :
namespace Blogs.Controllers
{
public class ToolsController : Controller
{
[Route("tools/datapermutator", Name = "DataPermutator"), HttpGet]
public ActionResult DataPermutator()
{
return View();
}
}
}
If you have a way to do it, it would be very helpful, thank you in advance!

Best way to prevent HTML Code in Textbox MVC Razor View

I have following code on my view.
This HTML code is used for search in website.
This view is not strongly typed view, so I can apply use DataAnnotation through model.
What is best view to validate that, this textbox should accept only alpha numeric characters?
HTML
<form action="Search" method="post" >
<div class="col-md-8">
<input type="text" name="name" placeholder="search" class="fullwidth" onkeypress="return BlockingHtml(this,event);" />
</div>
<div class="col-md-4">
<input type="submit" title="Search" value="Search" />
</div>
</form>
Javascript
function BlockingHtml(txt) {
txt.value = txt.value.replace(/[^a-zA-Z 0-9\n\r.]+/g, '');
}
Model:-
[StringLength(100)]
[Display(Description = "Name")]
[RegularExpression("(/[^a-zA-Z 0-9\n\r.]+/g", ErrorMessage = "Enter only alphabets and numbers of Name")]
public string Name{ get; set; }
Updated:-
View:-
<form action="Search" method="post" >
<div class="col-md-8">
<input type="text" name="name" id="txt" placeholder="search" class="fullwidth" onkeypress="BlockingHtml(this);" />
</div>
<div class="col-md-4">
<input type="submit" title="Search" value="Search" />
</div>
</form>
function BlockingHtml(txt) {
txt.value = txt.value.replace(/[^a-zA-Z 0-9\n\r.]+/g, '');
}
<form action="Search" method="post" >
<div class="col-md-8">
<input type="text" name="name" placeholder="search" class="fullwidth" onblur="return BlockingHtml(this,event);" />
</div>
<div class="col-md-4">
<input type="submit" title="Search" value="Search" />
</div>
</form>
Changed event onkeypress to onblur.

Resources