I'm creating a form in thymeleaf that contains a file upload field that's not part of my model.
When I load the page, thymeleaf complains and throws NotReadablePropertyException for that field.
How can I get thymeleaf to ignore the fact that the field does not exist on the model?
Code:
<div class="form-group"
th:classappend="${#fields.hasErrors('uploadFile')}? 'has-error'">
<label class="col-sm-12 control-label" style="text-align: left; margin-bottom: 7px;">Upload Photo</label>
<div class="col-sm-12" style="margin-bottom:5px;">
<div class="fileinput fileinput-new input-group" data-provides="fileinput">
<div class="form-control" data-trigger="fileinput">
<i class="glyphicon glyphicon-file fileinput-exists"></i>
<span class="fileinput-filename"></span>
</div>
<span class="input-group-addon btn btn-default btn-file">
<span class="fileinput-new">Select file</span>
<span class="fileinput-exists">Change</span>
<input type="file" name="uploadFile" accept="image/*" required>
</span>
Remove
</div>
<p id="error" style="position:absolute;color:#FF0000;margin-top:-7px"></p>
</div>
</div>
Error:
org.springframework.beans.NotReadablePropertyException: Invalid property 'uploadFile' of bean class [bean.Library]: Bean property 'uploadFile' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
the error that you get is because of the line
th:classappend="${#fields.hasErrors('uploadFile')}
that expects a field expression as a parameter.
You can replace
th:classappend="${#fields.hasErrors('uploadFile')}
with
th:classappend="${#fields.hasErrors('*')}
where the has-error class will appear if there is an error with any of the fields.
Or you can even replace it with
th:classappend="${#fields.hasErrors('global')}
that is not associated with any specific field in the form.
Or alternatively, you can add the field (uploadFile) in the model as a transient attribute.
Related
As said, I am trying to dynamically show or hide a Div using *ngIf in Angular 9 based on the value selected from dynamically generated drop down with static options.
I am very new to Angular and I directly jumped to Angular 9. I have been working on a model webapp just to see if I can get the hang of the tech.
I have a page that renders div rows based on the number of JSON objects.
Each row is an accordion in itself and each expanded accordion will in turn have 2-3 rows. In the expanded accordion I have dynamically generated a dropdown on a column.
Based on the drop down selection I need to show/hide a div in the other column on same expanded accordion.
Please do not give me a long route by using a event and a method defined in Typescript, I mean please pour in solutions but I am looking to come through this problem in the HTML page itself.
As of now the webapp has only one JSON object in the name "incidents", this is how iterate them
<div class="card" *ngIf='incidents && incidents.length' >
<div *ngFor = 'let incident of incidents ; let rowIndex = index'>
In the expanded Accordion am trying to achieve this.
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="'fixType' + rowIndex">Type of Fix </label>
<select id="'fixType' + rowIndex" class="form-control">
<option selected>{{incident.TypeOfFix}}</option>
<option value="1">Data Fix</option>
<option value="2">Code Fix</option>
<option value="3">User Education</option>
<option value="4">Work Around</option>
<option value="5">User Creation</option>
<option value="6">Configuration Changes</option>
<option value="7">Document Issue</option>
<option value="8">SP/Script Changes</option>
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="'EstClsDt' + rowIndex">Estimated Closure Date</label>
<div class="input-group">
<input #dp [id]="'EstClsDt' + rowIndex" class="form-control" placeholder="Estimated Closure Date"
[value]="incident.EstimatedClosureDT" [(ngModel)]="model" container="body" ngbDatepicker
#d1="ngbDatepicker">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar" (click)="d1.toggle()" type="button"></button>
</div>
</div>
</div>
</div>
<div class="col-md-4" *ngIf="incident.TypeOfFix == 'Code Fix' || 'fixType' + rowIndex === '2' ">
<div class="form-group">
<label for="'DepDt' + rowIndex">Deployment Date</label>
<div class="input-group">
<input #dp1 [id]="'DepDt' + rowIndex" class="form-control" placeholder="Estimated Closure Date"
[value]="incident.EstimatedClosureDT" [(ngModel)]="model" container="body" ngbDatepicker
#d2="ngbDatepicker">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar" (click)="d2.toggle()" type="button"></button>
</div>
</div>
</div>
</div>
</div>
<div class = "col-md-4" *ngIf = "incident.TypeOfFix == 'Code Fix'">
This line is working and div is hidden/shown based on the value returned from the JSON object but when trying to show/hide the div in the runtime with the help of below line.
I would need the correct version for the below line. There is no particular error thrown but the webapp does not react when I change the value of the drop down and div is neither shown nor hidden during runtime. I searched Online and people os different forums are suggesting to use ngModel or ngModule but if someone can help me with a clear syntax it would be great.
<div class="form-group" *ngIf = "'fixType' + rowIndex == '2' " >
Hope I have detailed enough, Please HELP.
Thanks.
i have page with the url that show my list of items:
https://localhost:123/AllSystems/List?systemTypeID=1
and inside this page i have search (i pass SearchTerm to list.cshtml.cs file ):
<form method="get">
<div class="form-group">
<div class="input-group">
<input type="search" class="form-control" asp-for="SearchTerm" />
<button type="button" class="btn btn-danger">
<span class="glyphicon glyphicon-search"></span> **Search**
</button>
</div>
</div>
</form>
when i click on Search button (inside the search form) i go to url:
https://localhost:123/AllSystems/List?SearchTerm=nba
that fine but i want to pass the systemTypeID=1 to from last url
(https://localhost:123/AllSystems/List?systemTypeID=1).
how i do it?
i want the result be something like that:
https://localhost:123/AllSystems/List?systemTypeID=1&SearchTerm=nba
thank's
you can pass multiple dynamic values to QueryString as below
you can set Value1 and Value2 and pass that values to your query string as below
string value1="1";
string value2="nba";
Response.Redirect("https://localhost:123/AllSystems/List?systemTypeID"+value1+"&SearchTerm="+value2);
in second page you can access the value like
string typeid= Request.QueryString["systemTypeID"];
string searchvalue = Request.QueryString["SearchTerm"];
I have a big problem about saving an Object list from Thymeleaf to the controller. Object List in thymeleaf is generated by Jquery. but I don't know how to get the data to Controller, that Object list doesn't know the size. Because users can add it anytime.
Please help me to send a list object in thymeleaf to controller.
I’ve Created a new class with 1 properties: ArrayList loaiDoans;
"LoaiDoan" is a Object that i want to save.
And using that class is an object to Save List "LoaiDoan" from thymeleaf to controller.
But List don't know the size first.because that genarated in thymeleaf. The first time i load the Model, the Model contain List is empty,so that list is not display in screen.
This is my class
public class ListLoaiDoan {
private ArrayList<LoaiDoan> loaiDoans;
//Getter Setter
}
My controller bind list object from controller to thymeleaf
#RequestMapping("/luunhieuobject")
public String LoadNhieuObjectCungLuc(Model model) {
ListLoaiDoan listLoaiDoanAAA = new ListLoaiDoan();
model.addAttribute("listLoaiDoan111",listLoaiDoanAAA);
return "/MHtrangchu/LuuNhieuObjCungLuc";
}
//This is the method save list Object from thymeleaf to controller
#PostMapping("/luunhieuobject")
public String processQuery(#ModelAttribute("listLoaiDoan111") ListLoaiDoan listLoaiDoan) {
System.out.println(listLoaiDoan.getLoaiDoans() != null ? listLoaiDoan.getLoaiDoans().size() : "List Empty");
System.out.println("--");
return "/MHtrangchu/LuuNhieuObjCungLuc";
}
LuuNhieuObjCungLuc.html
<form th:object="${listLoaiDoan111}" method="post" th:action="#{/luunhieuobject}">
<!--INPUT FIELDS-->
<div class="row">
<div class="col">
<div id="movieList">
<div class="row">
<div style="margin-left:100px;" class="col-4 form-group">tenloaidoan</div>
<div style="margin-left:100px;" class="col-4 form-group">madoan</div>
</div>
<div class="row item" th:each="row, stat : ${listLoaiDoan111.loaiDoans}">
<div class="col-lg-6 form-group">
<input th:field="*{loaiDoans[__${stat.index}__].tenloaidoan}" type="text" class="form-control"/>
</div>
<div class="col-lg-6 form-group">
<input th:field="*{loaiDoans[__${stat.index}__].madoan}" type="text" class="form-control"/>
</div>
</div>
</div>
</div>
</div>
<!--ADD NEW ROW BUTTON-->
<div class="row">
<div class="col">
<button type="button" class="btn btn-success" onclick="addRow()">Add row</button>
</div>
</div>
<!--SUBMIT FORM BUTTON-->
<div class="row text-right">
<div class="col">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
That not display annything in the screen, i know that because "listLoaiDoanAAA" is the empty and "th:each" in thymeleaf have nothing to show, how to generate "input" tag and save to controller help me !
I solved this problem !
Set a size for ArrayList before bind it to thymeleaf !
I save my day. thanks Stackoverflow.
i fix my controller like this
#GetMapping("/luunhieuobject")
public String LoadNhieuObjectCungLuc(Model model) {
ListLoaiDoan listLoaiDoanAAA = new ListLoaiDoan();
ArrayList<LoaiDoan> LDD = new ArrayList<LoaiDoan>(10);
listLoaiDoanAAA.setLoaiDoans(LDD);
model.addAttribute("listLoaiDoan111", listLoaiDoanAAA);
return "/MHtrangchu/LuuNhieuObjCungLuc";
}
I use Webdriver.io and want to select an element inside class "text-fields-container" (its is a password field). Both classes have same name. How can I select second class which has type="password".
<form>
<div class="text-fields-container">
<div>
<input type="text" class="text-field" placeholder="Email" required stype="margin-bottom: 1.125rem;">
</div>
<div>
<input type="password" class="text-field" placeholder="Password" required stype="margin-bottom: 5px;">
</div>
</div>
</form>
To select the second class which has type="password" you can use either of following Locator Strategies :
cssSelector :
"input.text-field[type='password']"
cssSelector (granular) :
"input.text-field[type='password'][placeholder='Password']"
xpath
"//input[#class='text-field' and #type='password']"
xpath (granular) :
"//input[#class='text-field' and #type='password' and #placeholder='Password']"
Try this: driver.findElement(By.xpath("(//input[#class='text-field'])[2]"));
I am working on an asp.net mvc 5 web application. And I have the following inside my edit/create view , to show two fields named ILIOP & Comment:
<div>
<span class="f"> #Html.DisplayNameFor(model=>model.Server.ILOIP)</span>
#Html.EditorFor(model =>model.Server.ILOIP)
#Html.ValidationMessageFor(model =>model.Server.ILOIP)
</div>
<div>
<span class="f">#Html.DisplayNameFor(model=>model.Server.Comment)</span>
#Html.TextAreaFor(model=>model.Server.Comment,new { #class = "textArea"})
#Html.ValidationMessageFor(model =>model.Server.Comment)
</div>
Now on my Post Edit action method I am checking for concurrency conflicts errors and display an error message beside the related fields:
if (databaseValues.ILOIP != clientValues.ILOIP)
ModelState.AddModelError("Server.ILOIP", "Current value: " + databaseValues.ILOIP);
if (databaseValues.Comment != clientValues.Comment)
ModelState.AddModelError("Server.Comment", " Current Value: " + databaseValues.Comment);
Now if there are error on those two fields (ILIOP & Comment) , then the comment field will get a red boarder around it, while the ILIOP will not , as follow:-
now here is the markup when the view is first rendered for the 2 fields (without errors):
<input class="text-box single-line" data-val="true"
data-val-length="The field ILOIP must be a string with a maximum length of 20."
data-val-length-max="20" id="Server_ILOIP" name="Server.ILOIP"
type="text" value="4" />
<span class="field-validation-valid" data-valmsg-for="Server.ILOIP" data-valmsg-replace="true"></span>
<textarea class="textArea" cols="20" data-val="true"
data-val-length="The field Comment must be a string with a maximum length of 256."
data-val-length-max="256" id="Server_Comment"
name="Server.Comment" rows="2">
</textarea>
and here is the markup when errors are displayed for the two fields :-
<input class="input-validation-error text-box single-line" data-val="true"
data-val-length="The field ILOIP must be a string with a maximum length of 20."
data-val-length-max="20" id="Server_ILOIP" name="Server.ILOIP"
type="text" value="4" />
<span class="field-validation-error" data-valmsg-for="Server.ILOIP"
data-valmsg-replace="true">Current value: 3</span>
<textarea class="input-validation-error textArea" cols="20" data-val="true"
data-val-length="The field Comment must be a string with a maximum length of 256."
data-val-length-max="256" id="Server_Comment"
name="Server.Comment" rows="2">
</textarea>
<span class="field-validation-error" data-valmsg-for="Server.Comment" data-valmsg-replace="true"> Current Value: 3</span>
So can anyone advice what is the reason that the ILIOP field does not show a red boarder around it when it has an error associated with it, while the comment field will show a red border ?
I suspect that your CSS for the page is defined in such a way that the textarea element is getting the red styling when both class input-validation-error and class textArea are on the element.
As an initial test of my hypothesis, see what happens if you change
#Html.EditorFor(model =>model.Server.ILOIP)
to
#Html.EditorFor(model =>model.Server.ILOIP, new { #class = "textArea"})
and retry your test case with this change. You may have to rebuild your source code and clear your browser's cache after making this change.