How to print 2 elements of list per 1 table row in JSF - jsf-2

I have a list of objects of particular class. Each object has two fields: id and value. I have to display that list by JSF, two elements per row, like that:
id1 value1 id2 value2
id3 value3 id4 value4
id5 value5 id6 value6
I don't want them to be just thrown into there in random way. I was rather thinking about displaying it in some table (with 4 columns), so they won't look messy (if one value is shorter than other).
I thought about using h:panelGroup, but i can not use c:forEach as my list is not available at that point (And yes, I have tired, it prints nothing there). ui:repeat can not be used with h:panelGroup.
I don't think I can use h:dataTable, as I need two elements of list being printed in one row and h:dataTable is rather not created with something like that in mind.
What can I do?
(I am JSF-noob, or... rather worst: I was JSF-noob, then hadn't contact with it for long time)

for solve this, you first have to group the list in pairs, then you can use ui:repetat + html table to print the results like:
#Named(value = "newJSFManagedBean")
#SessionScoped
public class NewJSFManagedBean implements Serializable {
private List<String> cars;
private List<List<String>> finalList;
/**
* Creates a new instance of NewJSFManagedBean
*/
public NewJSFManagedBean() {
}
#PostConstruct
public void loadCars() {
//Load main list
cars = new ArrayList<>();
cars.add("Volvo");
cars.add("Volvo1");
cars.add("Volvo2");
cars.add("Volvo3");
cars.add("Volvo4");
cars.add("Volvo5");
cars.add("Volvo6");
cars.add("Volvo7");
cars.add("Volvo8");
cars.add("Volvo9");
//Gruping in pairs
finalList = new ArrayList<>();
List<String> groupList = new ArrayList<>();
for (String car : cars) {
if (groupList.size() == 2) {
finalList.add(groupList);
groupList = new ArrayList<>();
}
groupList.add(car);
}
finalList.add(groupList);
}
public List<String> getCars() {
return cars;
}
public void setCars(List<String> cars) {
this.cars = cars;
}
public List<List<String>> getFinalList() {
return finalList;
}
public void setFinalList(List<List<String>> finalList) {
this.finalList = finalList;
}
}
and in the xhtml
<table>
<tr>
<th>ID</th>
<th>VALUE</th>
<th>ID</th>
<th>VALUE</th>
</tr>
<ui:repeat var="item"
value="#{newJSFManagedBean.finalList}">
<tr>
<ui:repeat var="subItem"
value="#{item}">
<td>someId</td>
<td>#{subItem}</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
result in :

Related

How to implement GroupBy using linq in razor view

How can this nested grouping be implemented in razor view?
This is what i have tried
Controller
public ActionResult SeniorityList()
{
var employee = db.Employees.GroupBy(f => f.Facility.FacilityName).ToList();
return View(employee.ToList());
}
However I don't know how to implement the foreach loop in view
Since you want the grouped data, i suggest you create a new class for that
public class GroupedItem
{
public string GroupName { set; get; }
public IEnumerable<Employee> Items { set; get; }
}
Now you can use the GroupBy method on your db.Employees collection and project the results to a collection of GroupedItem class objects.
var grouped = db.Employees
.GroupBy(f => f.Facility.FacilityName,i=>i,
(key,v)=>new GroupedItem { GroupName = key,Items = v})
.ToList();
return View(grouped);
the type of grouped variable will be a list of GroupedItem and we are passing that to the view. So make sure that your view is strongly typed to a collection of GroupedItem class.
#model IEnumerable<GroupedItem>
#foreach (var group in Model)
{
<h3>#group.GroupName</h3>
foreach (var p in group.Items)
{
<p>#p.Name</p>
}
}

Unable to return view model from view, model properties return just fine

I am new to web programming and MVC. I have searched for 2 days now and can not solve this.
If I try to return a collection of the model class. In the
controller I receive an empty collection.
If I try to return one instance of the model I receive null in the
controller.
If I try to return a property from the model, everything works as
expected.
Ideally I would like to return the current "item"
My Model
public class Images
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
Controller does not work
public void Commit(Images inI)
{
Debug.WriteLine((inI == null).ToString());
}
Controller does work
public void Commit(string Name)
{
Debug.WriteLine(Name);
}
View
#model IEnumerable<testweb.Models.Images>
....
#using (Html.BeginForm("Commit", "Images", FormMethod.Post))
{
<table class="table">
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Name)</td>
// Does Not work
<td>#Html.ActionLink("Commit", "Commit", new { inI = item })</td>
// Does as expected
<td>#Html.ActionLink("Commit", "Commit", new { Name = item.Name })</td>
</tr>
}
</table>
}
If you want to generate a url based on a models properties, then the usage is
#Html.ActionLink("Commit", "Commit", item)
since item is already an object. Note that the helper generates the route/query string values by using the .ToString() method of each property in your model, so this only works if you model contains string and value type properties (int, bool etc). If any properties of the model are complex objects or collections, then binding will fail because it would generate (say) ...&someCollection=System.Collections.Generic[someModel]. You also need to be cautious using this if the model contains many properties, or the values of the properties are long strings since you could exceed the query string limit and throw an exception.

Error when passing multiple tables from controller to view MVC4

I tried to pass 2 tables from Controller to view by using ViewModel
I declared:
public class Temp
{
public Models.ORDER_HEADER_INFO ORDER_HEADER_INFO { get; set; }
public Models.ORDER_ROUTING_DETAIL ORDER_ROUTING_DETAIL { get; set; }
}
In controller I write:
public ActionResult DataLoading()
{
using (Models.AllDataEntities et = new Models.AllDataEntities())
{
var Odata = (from ord in et.ORDER_ROUTING_DETAIL join
oh in et.ORDER_HEADER_INFO on ord.ORDER_NO equals oh.ORDER_NO
orderby ord.TARGET_COMPLETION_FLAG,oh.PRODUCT_START_DATE
select new {Order_No = oh.ORDER_NO,ROUTING_NAME = ord.ROUTING_NAME,
PJNO = oh.PJNO,DELIVERY_DESTINATION = oh.DELIVERY_DESTINATION,
}).ToList();
return View(Odata);
}
}
In view:
<table>
#for (int i = 0; i < Model.Count; i++ )
{
<tr>
<td>#Html.DisplayFor(m=>m[i].ORDER_HEADER_INFO.ORDER_NO)</td>
<td>#Html.DisplayFor(m=>m[i].ORDER_HEADER_INFO.PJNO)</td>
<td>#Html.DisplayFor(m=>m[i].ORDER_ROUTING_DETAIL.ROUTING_NAME)</td>
<td>#Html.DisplayFor(m=>m[i].ORDER_HEADER_INFO.DELIVERY_DESTINATION)</td>
</tr>
}
</table>
When i run the code, there is the exception like this:
The model item passed into the dictionary is of type
'System.Collections.Generic.List1[<>f__AnonymousType34[System.String,System.String,System.String,System.String]]',
but this dictionary requires a model item of type
'System.Collections.Generic.List`1[TIS.Models.Temp]'.
When I debug, Data is completely loaded to Odata, but I cannot understand what type of Odata.
You need to have this select statement. Instead of Anonymous Type, Select new Temp() { ... }. Reason is that your View Expects List<temp>, but you are passing list<AnonymousType> from controller.
var Odata = (from ord in et.ORDER_ROUTING_DETAIL join
oh in et.ORDER_HEADER_INFO on ord.ORDER_NO equals oh.ORDER_NO
orderby ord.TARGET_COMPLETION_FLAG,oh.PRODUCT_START_DATE
select new Temp() {ORDER_HEADER_INFO = oh, ORDER_ROUTING_DETAIL = ord }).ToList();
If you dont not want to use all the properties in the entities, then you need to create your DTO with the properties you want to use and map them in the linq query.
Your server side code should instantiate the Temp object while creating the list:
public ActionResult DataLoading()
{
using (Models.AllDataEntities et = new Models.AllDataEntities())
{
var Odata = (from ord in et.ORDER_ROUTING_DETAIL join
oh in et.ORDER_HEADER_INFO on ord.ORDER_NO equals oh.ORDER_NO
orderby ord.TARGET_COMPLETION_FLAG, oh.PRODUCT_START_DATE
select new Temp()
{
ORDER_HEADER_INFO = new ORDER_HEADER_INFO()
{
ROUTING_NAME = ord.ROUTING_NAME
},
ORDER_ROUTING_DETAIL = new ORDER_ROUTING_DETAIL()
{
Order_No = oh.ORDER_NO
}
}).ToList();
return View(Odata);
}
}
Your view can operate on this list like so:
#model IEnumerable<MvcApplication16.Models.Temp>
<table>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(item.ORDER_HEADER_INFO.ORDER_NO)</td>
<td>#Html.DisplayFor(item.ORDER_HEADER_INFO.PJNO)</td>
<td>#Html.DisplayFor(item.ORDER_ROUTING_DETAIL.ROUTING_NAME)</td>
<td>#Html.DisplayFor(item.ORDER_HEADER_INFO.DELIVERY_DESTINATION)</td>
</tr>
}
</table>
Note: As in your original Temp object definition, you have mapped entity directly, LINQ will throw error as you mentioned in the comment.
The entity or complex type 'Model.ORDER_HEADER_INFO' cannot be
constructed in a LINQ to Entities query.
You cannot (and should not be able to) project onto a mapped entity. You can, however, project onto an anonymous type or onto a DTO.
I suggest you create you modify your Temp definition and include properties that your want to send to view. That will make it a ViewModel object which is the right approach.
public class Temp
{
public string ORDER_NO { get; set; }
public string ROUTING_NAME { get; set; }
}

update a list of value in textfield in struts2

I am facing a problem in Struts2, In my sample application I have Array of objects (Say person name) , I need to display these names as a editable text fields , I am using Iterators for this , I am successful in diaplying, But When I cange the same value and submit the form. I am getting the entire array which holds null value.
Say for Exaple in my form bean I have a property
Name [] names;
In my JSP I have the iterator as
If there are 3 names then I can get these names on the UI if I can initialized them with some dummy value but when I edit and sumbit, then "names" array is not getting updated. Please help me in this regard
In Struts2, when you need to repopulate the list of bean items, you need to refer them through indices. Please refer the example below:
Bean class:
public class Person {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Action class:
public class PersonAction extends ActionSupport {
private List<Person> persons;
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
//Initial Load method
#Override
public String execute() {
persons = new ArrayList<Person>();
int alpha = 65;
for(int i = 0; i < 3 ; i++) {
Person person = new Person();
person.setId(i);
person.setName(String.valueOf((char)alpha++));
persons.add(person);
}
return SUCCESS;
}
//Function that handles the form submit
public String updatePerson() {
for(Person person : persons) {
System.out.println(person.getId() + ":" + person.getName());
}
return SUCCESS;
}
}
Page:
<s:form action="doUpdate">
<s:iterator value="persons" status="stat" var="person">
<s:textfield value="%{#person.name}" name="persons[%{#stat.count}].name"/><br/>
</s:iterator>
<s:submit value="Submit"/>
</s:form>
When you submit the above form, the url would look like doUpdate?persons[0].name=A1&persons[1].name=B1&persons[2].name=C1. Similarly if you need to update id of the first person object, you will append persons[0].id=3 to the url using form. In the <s:textfield value="%{#person.name}" name="persons[%{#stat.count}].name"/>, you tell that the predefined value is person's name, for each object. The name attribute is to set the rendered html input element; the name which will be referenced in the url when the form is submitted. You will get a clear idea if you look into the generated html.
Use the iterator tag of struts2, if list is not empty then use :
<s:iterator value="names" status="namesStatus">
<s:property/><br/>
</s:iterator>

How to load the related entities using Entity Framework and the Repository Pattern

This question is related to this
I have decided to change the Generic Repository pattern and used a specific repository for each entity. However I just cant find how to make it work because in my html I need to show some fields from related entities.
Is it better to replace Ienumerable with Iqueryable?
Repository Interface
public interface IApplicantPositionRepository : IDisposable
{
IEnumerable<ApplicationPositionHistory> GetApplicationPositionHistories(int applicantId, int positionId);
void Save();
}
Repository Interface Implementation.
public IEnumerable<ApplicationPositionHistory> GetApplicationPositionHistories(int applicantId, int positionId)
{
return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId);
}
Controller Method
public ViewResult History(int applicantId, int positionId)
{
var history=applicantPositionRepository.GetApplicationPositionHistories(applicantId, positionId);
return View(history);
}
Html.
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.applicantPosition.Position.name)
</td>
Personally I like IList<T> but thats a personal choice of course
To include a related table simply do (this syntax of not using a string for RelatedEntityName like .Include("RelatedEntityName") I think was added in 4.1 if I recall correctly:
return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId).Include(o=>o.RelatedEntityName);
Never return IQueryable from a repository. It's not easily testable since this is very provider specific.
I would also create separate methods if the caller does not require additional details either.
To answer your second question:
It is definitely preferable to use IQueryable instead of IEnumerable. Doing that you can do things like this:
Controller:
public ActionResult Index(int page = 1, int pageSize = 10)
{
IQueryable<Entity> items = repository.GetEntities();
items = items.ApplyPaging(page, pageSize);
return View(items);
}
You could create an extension method off of IQueryable called ApplyPaging that looks like:
public static class QueryableExtensions
{
public static IQueryable<T> ApplyPaging<T>(this IQueryable<T> source, int page = 1, int pageSize = 10)
{
return source.Skip((page - 1) * pageSize).Take(pageSize);
}
}
If it was IEnumerable then the paging could be done by the client instead of the database building the query correctly.

Resources