I am making an application which has student class.
it is as follows. this is sample pseudo description. (don`t bother about syntax)
public class student{
[required]
string name;
int id;
List<course> courses;
}
public class course{
[required]
string name;
}
student class has list of courses. now when i bind this as model to view. view has a text field for name and the grid for courses which has course name. if i submit the form with out entering the name of student.the validation fires automatically. but for the courses it is not firing up. though on the controller side model state is considered invalid. but client side validation is not firing up.
again i am posting sort of pesudocode can`t post actual code.
#using (Html.BeginForm("create", "student", FormMethod.Post, new { id = "createStudent" }))
{
#Html.TextboxFor(m=>m.name)
#Html.ValidationMessageFor(m=>m.Name)
<table><tr>
<td>
#Html.TextBox("courses[0].name")<br/>
#Html.ValidationMessage("course[0].name")
</td>
</table>
<input type="submit"></input>
}
now clicking on submit for doesnot fire validation for course name . but model.state is invalid.
if i enter something in course name the model is validated.
but i want to display validation on the page as it is firing for student name.
Please suggest me something
note:- i also tried (for course name) this.
#Html.TextBox("courses[0].Name", "", new { #class = "input-xlarge", id = "txtPropName" })
#Html.ValidationMessageFor(m=>m.courses[0].Name)
Related
I have a modelview that contains a list of ICustomInput values
public class DemoViewModel {
[Required]
public string FirstName {get; set;}
[Required]
public string LastName {get; set;}
[RequiredIf("DayPhoneRequired", true)]
public string DayPhone {get; set;}
public bool DayPhoneRequired {get; set;} = false;
public List<ICustomInput> CustomInputFields { get; set; } = new List<ICustomInput>();
}
an example of an ICustomInput
public class CustomTextInput : ICustomInput
{
public CustomField Field { get; }
public string DisplayName { get; set; }
[RequiredIf("DataValueRequired", true, ErrorMessage = "This is a required field")]
public virtual string DataValue { get; set; }
public bool DataValueRequired { get; set; } = false;
public virtual string ClassName => "CustomTextInput";
public string AssemblyName => "Application.Models";
}
The purpose of this is so that i can pull information from the DB about the custom input fields that the logged in client has requested on the form. One client may want a couple text fields, another client may want a drop down. These custom fields may or may not require input as well. (The CustomField object is an older object returned by the dataLayer and used heavily, I don't want to rebuild it, but assume it's just full of strings)
I have an editor template for the concrete implementations of ICustomInputs as well as custom binders that allow me to get the data on post. But the issue I'm having is that the RequiredIf attribute is setting the unobtrusive data values for client side validation the same for all ICustomInputs. It makes sense since they all have the same name for their dependent property, but it doesn't solve the issue I have.
My view displays the list of ICustomInput by simply:
#Html.EditorFor(model => model.CustomInputFields)
Then each concrete type that implements ICustomInput has it's own editorTemplate similar to:
<div class="columnPositioner">
<div class="inputContainer">
#Html.TextBoxFor(model => model.DataValue, new
{
#class = "inputFields input-lg form-control",
placeholder = Model.Field.Display
})
<span class="inputLabel">
#Html.LabelFor(model => model.Field.Display, Model.Field.Display)
</span>
#Html.ValidationMessageFor(model => model.DataValue, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.DataValueRequired)
</div>
</div>
The resulting HTML looks like:
<select name="CustomInputFields[0].DataValue" class="inputFields input-lg form-control" id="CustomInputFields_0__DataValue" data-val="true" data-val-requiredif-operator="EqualTo" data-val-requiredif-dependentvalue="True" data-val-requiredif-dependentproperty="DataValueRequired" data-val-requiredif="This is a required field"><option value="">TEST01</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
</select>
<input name="CustomInputFields[0].DataValueRequired" class="hasContent" id="CustomInputFields_0__DataValueRequired" type="hidden" value="True" data-val-required="The DataValueRequired field is required." data-val="true">
<input name="CustomInputFields[1].DataValue" class="inputFields input-lg form-control" id="CustomInputFields_1__DataValue" type="text" placeholder="TEST02" value="" data-val="true" data-val-requiredif-operator="EqualTo" data-val-requiredif-dependentvalue="True" data-val-requiredif-dependentproperty="DataValueRequired" data-val-requiredif="This is a required field">
<input name="CustomInputFields[1].DataValueRequired" id="CustomInputFields_1__DataValueRequired" type="hidden" value="False" data-val-required="The DataValueRequired field is required." data-val="true">
The hidden field is named properly, but how can I get the attribute to set the data-val-requiredif-dependentproperty to the actual id/name on the hidden field?
I do not currently have a custom editor template for the List. I did have one, but couldn't get it to bind the data back correctly. Dropping the editor template on the List and building unique editor templates for the concrete implementations of ICustomInput gave me all the UI layout control I needed and bound the data correctly, but now I can't get the client side validation to work properly. If it's just a editor template, what might that look like?
Update
This is A fix, but I don't like it. I have a javascript that's already doing an .each through inputs to apply styles so I added this to the .each:
function requiredIfHack($input) {
var depPropVal = $input.data("val-requiredif-dependentproperty");
//return if the value exists
if ($("#" + depPropVal).length) return;
//it doesn't. it's missing the parent object name
var parentName = $input.attr("name").split(".")[0].replace("[", "_").replace("]", "_");
$input.data("val-requiredif-dependentproperty", parentName + "_" + depPropVal);
}
It solves the problem, but I don't think it should be a problem that is the js responsibility to solve. And since it's a pretty sneaky fix, it could trip up others trying to work on this code in the future. I still want to find a better way to do it.
I have a model (called plan) which one of its properties is a list (ICollection) of Exercises (which is another model):
public int Id { get; set; }
public virtual ICollection<Exercise> Exercises { get; set; }
So i tried to create a view that creates a plan and another view to add Exercises to the plan from exercises in the database.
So i did a loop that ranges all the exercises from the DB and for each one i added a check box with and id same as the id of the exercise and i thought i could do something with it but i tried so many things and ways and i couldn't even sent the input of the check boxes to the controller.
I must say that i'm kinda new with programming with mvc and i tried to look all over the internet and i didn't really know people who knows to program so this is really my last chance to solve it. Sorry if it was a long post or too easy for you to even comment but i really need this.
This is very specific for my project and what i stacked on was to sent the input to the controller but i'm open to different solutions cause i'm desperate.
public async Task<ActionResult> AddExercises(string id,int[] selectedExercises)
{
List<Exercise> list = new List<Exercise>();
foreach (int i in selectedExercises)
{
list.Add(db.Exercises.Find(i));
}
db.Plans.Find(id).Exercises = list;
await db.SaveChangesAsync();
return RedirectToAction("index");
}
I am sure its wrong and the view i tried is:
#using (Html.BeginForm("index", "Plans"))
{
#Html.AntiForgeryToken()
foreach (var i in Model.Exercises)
{
<table class="table">
<tr>
<td>#Html.DisplayFor(modelItem => i.Level)</td>
<td>#Html.DisplayFor(modelItem => i.Description)</td>
<td>#Html.DisplayFor(modelItem => i.MoreDescription)</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = i.Id }) |
#Html.ActionLink("Details", "Details", new { id = i.Id }) |
<input type="checkbox" class="selectedObjects" id="i.id" /> |
</td>
</tr>
</table>
}
#Html.ActionLink("Finish", "AddExercises")
}
I use viewModel PlanExercise in this view
Your checkboxes do not have either a name attribute or a value attribute so there is nothing to submit. You html needs to be
<input type="checkbox" name="selectedExercises" value="#i.id" />
and then in order to submit the form, you need a submit button (remove #Html.ActionLink("Finish", "AddExercises"))
<input type="submit" value="Save" />
and the form needs to be (assuming the controller is FinishController)
#using (Html.BeginForm("AddExercises", "Finish"))
and the method needs to be marked with the [HttpPost] attribute.
I'm creating a webshop and I have it taking info from a SQL database and putting in into an array of items in a bean called MySQLBean. So far so good.
private void doSelect() {
try {Connection conn = ds.getConnection();
try {PreparedStatement dbQuery = conn.prepareStatement("SELECT * from item");
ResultSet resultset = dbQuery.executeQuery();
results.clear();
while(resultset.next()){
results.add(new Item(resultset.getInt("id"),
resultset.getString("name"),
resultset.getDouble("price"),
resultset.getString("description")));
}
}
finally {conn.close();
}
}
catch (SQLException e){e.printStackTrace();}
}
Now I have a button on the site which sends the ID from the item intended for purchase to another bean called ShoppingCartBean.
<h:form prependId="false">
<h:commandLink id="addToCart"
action="#{shoppingCartBean.addToCart(item.id)}"
styleClass="btn btn-default">
<i class ="icon-search"></i> #{msgs.addToCart}
</h:commandLink>
</h:form>
After having sent the item.id data to my shoppingCartBean, I wish to select the item with the corresponding id from the array I loaded earlier and add that entire item to a new array so that I can print the list of items to my user at a later time. But I'm completely stumped on how to do this.
EDIT: Formatted wrong
EDIT: Attempted to clarify question
Just send the entire item #{item} instead of only its ID #{item.id}.
In other words, instead of
action="#{shoppingCartBean.addToCart(item.id)}"
do
action="#{shoppingCartBean.addToCart(item)}"
with
public void addToCart(Item item) {}
I have a database table with some oneToMany relations.
this is fragment of the entity:
#OneToMany(mappedBy="auction")
private List<Biding> bidings;
now i want to print higher bid on my jsf website:
<ui:repeat var="singleAuction" value="#{auctionListBean.auctionList}" varStatus="status">
<h:outputLabel value="#{singleAuction.getHigherBid()}"/>
</ui:repeat>
this my aucListBean
#ManagedBean
public class AuctionListBean
{
#PersistenceContext()
EntityManager entityManager;
public List<AuctionBean> getAuctionList() {
Query query = entityManager.createQuery("SELECT e FROM Auction e");
#SuppressWarnings("unchecked")
List<AuctionBean> resultList = (List<AuctionBean>) query.getResultList();
return resultList;
}
}
I also have AuctionBean class which I used before to add new auction. Now I want to create a bean which has one property: list of auctionBean. I populate it using my entity and cast it to AuctionBean. In AuctionBean class I implemented mentioned method:
public double getHigherBid()
{
double higherBid = 0;
for(Biding a : bidings)
{
if(a.getCurrentPrice() > higherBid)
higherBid = a.getCurrentPrice();
}
return higherBid;
}
The problem is "Method not found". It seems like it still dont even use AuctionBean class for some reason. It may be a problem why it cannot see the method. I am doing it right and where is the problem exactly? Could you help?
I have two suggestions:
1. Use singleAuction.higherBid, not singleAuction.getHigherBid()
2. Specify the target class of your query. Here's an example:
return entityManager.createQuery("SELECT e FROM Auction e", AuctionBean.class)
.getResultList();
I don't seem to get multiple selection in PrimeFaces dataTables working.
I'm trying to implement a list of clients (dataList) and show their respective bookings in nested dataTables with a possibility to select multiple bookings for billing:
<p:dataList value="#{clientController.allClients}" var="client">
<p:column>
<p:dataTable value='#{client.bookingsDataModel}' var='item' selection="#{client.bookingsToBill}">
<p:column selectionMode="multiple" />
</p:dataTable>
</p:column>
</p:dataList>
My controller and backing bean classes:
public class ClientController {
public List<Client> getAllClients() {
return clients;
}
}
public class Client {
private List<Booking> bookings;
private Booking[] bookingsToBill;
public LeistungDataModel getBookingsDataModel() {
return new BookingsDataModel(bookings);
}
public Booking[] getBookingsToBill() {
return bookingsToBill;
}
public void setBookingsToBill(Booking[] bookingsToBill) {
this.bookingsToBill = bookingsToBill;
}
}
The data model class:
public class BookingsDataModel extends ListDataModel<Booking> implements SelectableDataModel<Booking> {
public BookingsDataModel(List<Booking> data) {
super(data);
}
#Override
public Booking getRowData(String rowKey) {
List<Booking> bookings = (List<Booking>) getWrappedData();
for(Booking booking : bookings) {
if(("booking_"+booking.getId().toString()).equals(rowKey)) {
return booking;
}
}
return null;
}
#Override
public Object getRowKey(Booking booking) {
return "booking_"+booking.getId().toString();
}
}
The browser posts the following data to the server, when I submit the form with my selections:
j_idt9%3Aj_idt13%3A0%3Aj_idt15_selection:booking_300,booking_301,booking_302
j_idt9%3Aj_idt13%3A1%3Aj_idt15_selection:booking_566,booking_567
j_idt9%3Aj_idt13%3A2%3Aj_idt15_selection:
Also, I found during debugging that the getRowData method of the BookingsDataModel returns the correct Booking objects (the selected ones).
However, always empty arrays are passed to the setBookingsToBill of my Client objects. What could be going wrong here?
Update:
An empty array is only passed the first Client objects - it doesn't matter if a booking has been selected or not. All other Client objects' setBookingsToBill methods are called with a parameter value of null.
Not really, if you want multiple selection with check box you have to do as jfs did:
In the showcase there is one example showing just that. It will create a column containing the boxes for the user to select. You can also do as you've said, using an attribute of p:dataTable, however this will not create the boxes and the user will have to control+click to do multiple select.
The selectionMode should be a part of the <p:dataTable> tag.
Here is a link to the showcase which has an example.
http://www.primefaces.org/showcase/ui/datatableRowSelectionMultiple.jsf