Setting th:field from another variable in Thymeleaf - thymeleaf

I have this code below where I try to set a field with a value from the viewModel. I tried to follow this and this by removing th:field and adding only th:value + html name and id but I still get null in the model. Not really sure what I am doing wrong.
<tr th:each="r, rowStat : ${roomViewModels}">
<td th:text="${r.type} ">
</td>
<td th:text="${#numbers.formatCurrency(r.price)}"></td>
<td>
<input class="form-control" type="number" min="1" max="10"
th:field="*{roomType[__${rowStat.index}__].numberOfRooms}"
id="numberOfRooms" name="numberOfRooms"/>
<input th:value="${viewModel.rooms[__${rowStat.index}__].getType()}"
name="type"
id="type"
type="hidden"/>
Controller
#PostMapping("/create-booking")
public String createBooking(#Valid BookingBindingModel bindingModel, BindingResult br,RedirectAttributes rAtt, #AuthenticationPrincipal CustomUser user,
#RequestParam(value = "id") Long id){
if (br.hasErrors()) {
System.out.println(br);
rAtt
.addFlashAttribute("bindingModel", bindingModel)
.addFlashAttribute("org.springframework.validation.BindingResult.bindingModel", br);
return "redirect:booking-form";
}
Controller:
#GetMapping("/booking-form")
public String bookingForm(HttpServletRequest request, Model model) {
Cookie[] cookies = request.getCookies();
long id = 0;
for (Cookie cookie : cookies) {
if (cookie.getName().equals("id")) {
id = Long.parseLong(cookie.getValue());
break;
}
}
AccommodationViewModel viewModel = this.accommodationService.findById(id);
List<RoomViewModel> roomViewModels = viewModel.getRooms();
model
.addAttribute("viewModel", viewModel)
.addAttribute("roomViewModels", roomViewModels);
return "booking-form" ;
}
ViewModel:
public class AccommodationViewModel {
private Long id;
private String name;
private String category;
private String city;
private String address;
private Integer postalCode;
private String imageUrl;
private List<RoomViewModel> rooms = new ArrayList<>();
private String type;
private String cancellationPolicy;
private String paymentPolicy;
private LocalTime checkInTime;
private LocalTime checkOutTime;
Binding Model:
public class BookingBindingModel {
#Future
#DateTimeFormat(pattern = "yyyy-MM-dd")
#NotNull(message = "Check out date is required!")
private LocalDate checkOut;
#NotNull(message = "Number of rooms is required!")
private List<RoomBindingModel> roomType;
#NotNull(message = "Number of people is required!")
private Integer numberOfPeople;

Related

How to access DropDown values in Struts 2 Action

My requirement is, at beginning I want to show users data on page and when user make changes in form, I want to access changed data.
Below is my code in Action class,
public class DisplayData extends ActionSupport implements ModelDriven<List<User>>, Preparable {
private List<User> userList;
#Override
public void prepare() throws Exception {
userList = new ArrayList<User>();
userList.add(new User("Demo","N"));
userList.add(new User("Demo1","Y"));
userList.add(new User("Demo2","Y"));
userList.add(new User("Demo3","N"));
}
#Override
public List<User> getModel() {
return userList;
}
public String execute(){
for (User value: userList) {
System.out.println(value.getName() +":"+value.getFlag());
}
return "success";
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
User class,
public class User implements Serializable
{
private String name;
private String flag;
public User() {}
public User(String name,String flag) {
super();
this.name = name;
this.flag = flag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
Code in Jsp page,
<s:form name="getData" action="getData" method="post">
<table>
<s:iterator value="model" status="rowStatus">
<tr>
<td>
<s:textfield name="model[%{#rowStatus.index}].name" value="%{model[#rowStatus.index].name}"/>
<s:select name="%{model[#rowStatus.index].flag}" value="%{model[#rowStatus.index].flag}"
list="#{'Y':'Yes','N':'No'}" />
</td>
</tr>
</s:iterator>
</table>
<s:submit name="ok" value="ok" />
</s:form>
When page get rendered, it shows appropriate value of textfield and dropdown.
If I changed the values in Textfield and droprdown and submit the form then I am getting modified value of textfield but for the dropdwon it shows old value. How can I access selected value of dropdown?
Got the answer... :)
It was syntax mistake. Instead of
<s:select name="%{model[#rowStatus.index].flag}" value="%{model[#rowStatus.index].flag}"
list="#{'Y':'Yes','N':'No'}" />
Use
<s:select name="model[#rowStatus.index].flag" value="%{model[#rowStatus.index].flag}"
list="#{'Y':'Yes','N':'No'}" />
I have used %{ } in name attribute..

ASP.NET MVC HtmlHelper extension method to wrap around only if it has content

I am making an configurable form—an admin selects which inputs are displayed. The inputs are wrapped by fieldsets.
I want to make a HtmlHelper to generate fieldset only if it has content—at least one input field to prevent such situations
<fieldset id="Name">
<legend>Name</legend>
<input type="text" placeholer="Forename"></input>
<input type="text" placeholer="Surname"></input>
</fieldset>
<fieldset id="Address">
<legend>Address</legend>
</fieldset>
that we have empty fieldset like that with address.
I've made a FieldSetHelper
public class FieldSetHelper: IDisposable
{
private readonly HtmlHelper _htmlHelper;
private readonly string _fieldSetId;
private readonly string _legendId;
private readonly string _legendText;
public FieldSetHelper(HtmlHelper htmlHelper, string fieldSetId, string legendId, string legendText)
{
_htmlHelper = htmlHelper;
_fieldSetId = fieldSetId;
_legendId = legendId;
_legendText = legendText;
_htmlHelper.ViewContext.Writer = new StringWriter();
OpenFieldSet();
AddLegend();
}
private void OpenFieldSet()
{
string id = string.IsNullOrWhiteSpace(_fieldSetId) ? string.Empty : string.Format(" id=\"{0}\"", _fieldSetId);
_htmlHelper.ViewContext.Writer.WriteLine(string.Format("<fieldset" + id + ">"));
}
private void CloseFieldSet()
{
_htmlHelper.ViewContext.Writer.WriteLine(string.Format("</fieldset>"));
}
private void AddLegend()
{
string id = string.IsNullOrWhiteSpace(_legendId) ? string.Empty : string.Format(" id=\"{0}\"", _legendId);
_htmlHelper.ViewContext.Writer.WriteLine("<legend"+id+">");
_htmlHelper.ViewContext.Writer.WriteLine(_legendText);
_htmlHelper.ViewContext.Writer.WriteLine("</legend>");
}
public void Dispose()
{
CloseFieldSet();
}
But I don't know how to not generate it if its content is empty.
Here is part of the View:
using (Html.BeginFieldSet("Address", null, "Address"))
{
#Html.EditorFor(m => m.Address, new {Model.VisibleInputFields})
}
I recently had a similar situation. I was trying to add some "No Items Here" text if the outer element (the one generated from the using element) did not have any items. This is an untested modified version of what I ended up doing but if you are still looking for an answer it should get you close.
public class FieldSetHelper: IDisposable
{
private readonly HtmlHelper _htmlHelper;
private readonly string _fieldSetId;
private readonly string _legendId;
private readonly string _legendText;
public FieldSetHelper(HtmlHelper htmlHelper, string fieldSetId, string legendId, string legendText)
{
_htmlHelper = htmlHelper;
_fieldSetId = fieldSetId;
_legendId = legendId;
_legendText = legendText;
_htmlHelper.ViewContext.Writer = new StringWriter();
OpenFieldSet();
AddLegend();
}
private string BuildOpenFieldSetString(){
string id = string.IsNullOrWhiteSpace(_fieldSetId) ? string.Empty : string.Format(" id=\"{0}\"", _fieldSetId);
return string.Format("<fieldset" + id + ">");
}
private void OpenFieldSet()
{
_htmlHelper.ViewContext.Writer.WriteLine(BuildOpenFieldSetString());
}
private void CloseFieldSet()
{
_htmlHelper.ViewContext.Writer.WriteLine(string.Format("</fieldset>"));
}
private void AddLegend()
{
string id = string.IsNullOrWhiteSpace(_legendId) ? string.Empty : string.Format(" id=\"{0}\"", _legendId);
_htmlHelper.ViewContext.Writer.WriteLine("<legend"+id+">");
_htmlHelper.ViewContext.Writer.WriteLine(_legendText);
_htmlHelper.ViewContext.Writer.WriteLine("</legend>");
}
public void Dispose()
{
var htmlString = _htmlHelper.ViewContext.Writer.ToString();
var index = htmlString.Trim().LastIndexOf(BuildOpenFieldSetString().Trim());
if(html.IndexOf("<input", index) == -1){
_htmlHelper.ViewContext.Writer = new StringWriter();
_htmlHelper.ViewContext.Writer.WriteLine(html.SubString(0,index));
}else{
CloseFieldSet();
}
}

returning data from model to view

now how to get data back in View from model ?
my code:
View:
#using (Html.BeginForm("register","Home", FormMethod.Post, new {id="submitForm"}))
{
<div>
<i>#Html.Label("Name:")</i>
#Html.TextBox("txtboxName")
</div>
<div>
<i>#Html.Label("Email:")</i>
#Html.TextBox("txtboxEmail")
</div>
<div>
<i>#Html.Label("Password:")</i>
#Html.Password("txtboxPassword")
</div>
<div>
<button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>
</div>
}
controller:
[HttpPost]
public ActionResult register(string command, FormCollection formData )
{
if (command == "Submit")
{
var name = formData["txtboxName"];
var email = formData["txtboxEmail"];
var pwd = formData["txtboxPassword"];
database db = new database();
db.connectDB(name, email, pwd);
ViewBag.Message = email;
}
return View();
}
}
}
Model:
namespace LoginSys.Models
{
public class database
{
public void connectDB(String name, String email, String pwd)
{
String conStr = "Data Source=HUNAIN-PC;Initial Catalog=registration;User ID=sa;Password=abc123!##";
sqlconnection sqlCon = new sqlconnection(conStr);
string comm = "insert into tblRegister values('"+name+"','"+email+"','"+pwd+"')";
sqlcommand sqlCom = new sqlcom(comm, con);
try
{
sqlCon.Open();
sqlCon.executeNonQuery();
}
catch(exception exc)
{
//code
}
finally
{
con.close();
}
}
}
}
now how to return NO OF ROWS EFFECTED BY EXECUTENONQUERY statement or suppose any thing to return ? simple words and please help me in this approach, will use advance techniques later.
If you want to return something, you can use SqlParameter ParameterDirection.Output like this:
SqlCommand cc = new SqlCommand(connStr); // connection string
cc.CommandText = "insert into tblRegister (Name, Email, Pwd) values (#name, #email, #pwd); select #result = ##identity";
cc.AddWithValue("#name", name);
cc.AddWithValue("#email", email);
cc.AddWithValue("#pwd", pwd);
cc.Parameters.Add("#result", SqlDbType.Int);
cc.Parameters["#result"].Direction = ParameterDirection.Output;
cc.ExecuteNonQuery();
// returs identity key
int id = (int)cc.Parameters["#result"].Value;
Then you can return this id from your function, but you have to modify it's prototype:
public int connectDB(String name, String email, String pwd) // changed void to int
{
// ...
return id;
}
Then you can simply put this value to ViewBag, or use other ways to pass it to your view:
database db = new database();
ViewBag.Id = db.connectDB(name, email, pwd);
ViewBag.Message = email;
If you use ViewBag, you can access it in your view with #ViewBag.Id

MVC 3 CheckboxList and me...Part 3. Try specifying the type arguments explicitly

This IS fun.
Ok, I have the following model(s):
public class My : BusinessCategory
{
[Display(Name = "What types of energy do you use?")]
public List<MyTypes> MyTypeList { get; set; }
public bool? FirstOption { get; set; }
public bool? SecondOption{ get; set; }
public bool? ThirdOption{ get; set; }
public bool? FourthOption { get; set; }
}
Where MyTypes:
public class MyTypes
{
public int MyTypeId { get; set; }
public string MyTypeName { get; set; }
public bool? MyTypeValue { get; set; }
}
My controller is as follows:
public ActionResult My(Guid id)
{
try
{
var model = Model(id);
SetMyTypeList(model.My);
ViewBag.MyTypeMe = new MultiSelectList(model.My.MyTypeList, "MyTypeValue", "MyTypeName");
return View(model.My);
}
catch (Exception ex)
{
ExceptionHelper.WriteLog(ex);
return RedirectToAction("Error");
}
}
private void SetMyTypeList(My model)
{
model.MyTypeList = new List<MyTypes>();
model.MyTypeList.Add(new MyTypes { MyTypeId = 1, MyTypeName = GetName.GetDisplayName(model, m => m.FirstOption), MyTypeValue = model.FirstOption });
model.MyTypeList.Add(new MyTypes { MyTypeId = 2, MyTypeName = GetName.GetDisplayName(model, m => m.SecondOption), MyTypeValue = model.SecondOption});
model.MyTypeList.Add(new MyTypes { MyTypeId = 3, MyTypeName = GetName.GetDisplayName(model, m => m.ThirdOption), MyTypeValue = model.ThirdOption});
model.MyTypeList.Add(new MyTypes { MyTypeId = 4, MyTypeName = GetName.GetDisplayName(model, m => m.FourthOption), MyTypeValue = model.FourthOption });
}
public static string GetDisplayName<TModel, TProperty>(TModel model, Expression<Func<TModel, TProperty>> expression)
{
return ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, new ViewDataDictionary<TModel>(model)).DisplayName;
}
And finally the view is as follows:
#model Valpak.Websites.HealthChecker.Models.My
#{
ViewBag.Title = "My";
}
<h2>
My</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>My Management</legend>
<div style="text-align: left; padding-left: 47%;">
#Html.ListBoxFor(model => model.MyTypeList, ViewBag.MyTypeMe as MultiSelectList)
#Html.CheckBoxListFor(model => model.MyTypeList, ViewBag.EnergyTypeMe as MultiSelectList, Model.ReviewId)
</div>
<p>
<input type="submit" value="Continue" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Cancel and return to categories", "BusinessSummary", new { id = Model.ReviewId })
</div>
CheckboxListFor, if it was working, would use the following extension:
public static class HtmlHelper
{
//Extension
public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty[]>> expression, MultiSelectList multiSelectList, object htmlAttributes = null)
{
//Derive property name for checkbox name
MemberExpression body = expression.Body as MemberExpression;
string propertyName = body.Member.Name;
//Get currently select values from the ViewData model
TProperty[] list = expression.Compile().Invoke(htmlHelper.ViewData.Model);
//Convert selected value list to a List<string> for easy manipulation
List<string> selectedValues = new List<string>();
if (list != null)
{
selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); });
}
//Create div
TagBuilder divTag = new TagBuilder("div");
divTag.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);
//Add checkboxes
foreach (SelectListItem item in multiSelectList)
{
divTag.InnerHtml += String.Format("<div><input type=\"checkbox\" name=\"{0}\" id=\"{0}_{1}\" " +
"value=\"{1}\" {2} /><label for=\"{0}_{1}\">{3}</label></div>",
propertyName,
item.Value,
selectedValues.Contains(item.Value) ? "checked=\"checked\"" : "",
item.Text);
}
return MvcHtmlString.Create(divTag.ToString());
}
}
Can someone you explain in very simplistic terms (I’m a bit dense) why I can use the ListBoxFor example but this dies and gives me the following error when I use the checkbox?
CS0411: The type arguments for method 'Extensions.HtmlHelper.CheckBoxListFor<TModel,TProperty>(System.Web.Mvc.HtmlHelper<TModel>, System.Linq.Expressions.Expression<System.Func<TModel,TProperty[]>>, System.Web.Mvc.MultiSelectList, System.Guid, object)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Can anyone offer any sort of work around as I’d quite like to use my :’(
As always, apologies for my ignorance.
In the signature of the extension method you have the following second argument:
Expression<Func<TModel, TProperty[]>> expression,
This basically means that the expression must return an array of TProperty => TProperty[]
whereas in your view model you have a List<T>:
public List<MyTypes> EnergyTypeList { get; set; }
and inside your view you are using:
model => model.EnergyTypeList
Your code doesn't work because List<EnergyTypeList> is not the same thing as EnergyTypeList[].
So you have different possibilities. Either change the type in your view model to match the one in your helper or use change your helper to use a List or even better an IEnumerable<TProperty>. This way the extension method will work even with arrays.

Display edit Employee's profile using jsf

Using jsf I want to edit a employee profile, when user will click on any particular datatable row,then
I am able to get all that deatils of selected patient in an
arraylist. Now I want to set all the attritbutes in arraylist to
page1.xhtml backingbean , so When user will select a particular row,
he will navigate to page1.xhtml where he will get all these fields in
the form set already by arraylist attributes.
I am trying in this way.
> page1.xhtml
<h:outputLabel value="Name" />
<p:inputText id="name1" value="#{employeeBB.emp.name}" >
</p:inputText>
<h:outputLabel value="age" />
<p:inputText id="ag" value="#{employeeBB.emp.age}" >
</p:inputText>
<h:outputLabel value="code" />
<p:inputText id="code1" value="#{employeeBB.emp.code}" >
</p:inputText>
#ManagedBean(name = "employee")
#ViewScoped
public class emp {
private String name;
private String age;
private String code;
public String getName()
{ return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
#SessionScoped
#ManagedBean
public class EmployeeBB implements serializable{
private Employe emp;
public Employee getEmp() {
return emp;
}
public void setEmp(Employee emp) {
this.emp = emp;
}
}
#SessionScoped
#ManagedBean
public class AddEmployeeBB{
private ArrayList<Employee>empList;
private ArrayList<Employee>empList;
public ArrayList<Employee> getEmpList() {
if(empList==null){
empList=new ArrayList<Employee>();
}
return empList;
}
public void setEmpList(ArrayList<Employee> empList) {
this.empList = empList;
}
public void method() throws IOException{
String code='123';
EmployeeDAO obj=new EmployeeDAO(); // DAO class
empList=obj.getAllEmplInfo(code); // will get all needed information about employee of this code in this arrayist
for(int i=0;i<empList.size();i++){
String name=empList.get(i).getName();
String age=empList.get(i).getAge();
String code=empList.get(i).getCode();
Employee e=new Employee();
e.setName(name);
e.setAge(age);
e.setCode(code);
EmployeeBB obj1=new EmployeeBB();
obj1.setEmp(e); // now according to my logic object e will set to emp object of Employee, and
// that means all these values name ,agem and code will be set to my page1.xhtml and I will be able to see it.
}
}
But I am unable to get pag1.xhtml with filled values.
Show me the way.
The reason for it not being shown is that you are setting values in a object which you are creating
EmployeeBB obj1=new EmployeeBB();
obj1.setEmp(e);
JSF lifecycle doens't know about this object and everytime you are seeing blank.
In AddEmployeeBB add this
#ManagedProperty(value="employeeBB")
private EmployeeBB employeeBB = null; // create getter setter for this
then instead of this :
EmployeeBB obj1=new EmployeeBB();
obj1.setEmp(e);
Use this:
this.employeeBB.setEmp(e);

Resources