Table merge cells - Vaadin - vaadin

I'm Creating table with Vaadin. Some of the cells are repeating. So I want them to merge in one cell, as you can see on the image:
The first image show how the table looks now, and the second is how I want to look with merged cells.
I'm using this code:
Table table = new Table(AppData.getMessage("menu.report2"));
table.addContainerProperty(tableHeaders[0], String.class, null);
table.addContainerProperty(tableHeaders[1], String.class, null);
table.addContainerProperty(tableHeaders[2], String.class, null);
table.addContainerProperty(tableHeaders[3], String.class, null);
List<User> employeeList = employeeDAO.findAllEmployees();
int i;
for (i = 0; i < employeeList.size(); i++) {
User employee = employeeList.get(i);
table.addItem(new Object[]{
CaseStatus.OPEN,
tasksDAO.countTasks(CaseStatus.OPEN),
employee.getFirstAndLastName(),
tasksDAO.countTasks(employee, CaseStatus.OPEN)},
i);
}
for (int j = 0; j < employeeList.size(); j++) {
User employee = employeeList.get(j);
table.addItem(new Object[]{
CaseStatus.CLOSED,
tasksDAO.countTasks(CaseStatus.CLOSED),
employee.getFirstAndLastName(),
tasksDAO.countTasks(employee, CaseStatus.CLOSED)},
i + j);
}
table.setPageLength(table.size());
addComponent(table);
setComponentAlignment(table, Alignment.TOP_CENTER);
setMargin(true);

I think, this is not possible in "normal way". But I have an idea how to simulate this.
First solution:
You could simply use GridLayout to build grid as you want. Then nothing limit your imagination beside size of such grid. It shouldn't be to big (also pointed here).
Second solution:
Another advice is a bit crazy.
Disable Table/Grid stripes.
In group of similar cells just fill only first row. Left rest blank (or space in string).
Then you dispose of repeated data (from your first and second column), but you can't alignment them vertically (the text will stay at top - first row from group).
Third solution:
Check Add-ons list. For example ItemGrid.

Related

Remove spacing between the first row and second row in the Gridlayout

Thank you very much for your help in advance.
Let me explain the problem,
I have grid layout where I am adding the labels in the first row (its called header row). In the next 5 rows, I am adding text field, combo and date fields.
The problem I am facing is, I would like to remove the space between header(first) row and second row and continue to have default space from second row to the last rows. I have highlighted the space as red line in the snapshot
Please find the snapshot in attachment.
Any hints, please advise.
As I've mentioned in the comments, position of a component in a GridLayout defined by a top value in css. So you would need to change it if you want to re-position(remove space, in this case) an element. The problem here is that
GridLayout not necessary starts from top, so you would need to figure out a correct value for a top,
and then you would need to differentiate a correct component(label in this case) using :n-th child, since a class name applied to a component, is not propagated to a parent's v-gridlayout-slot.
As for an alternative, you could add a common styleName to all components (except labels) and using this style set margins(left, right, bottom)to all the components. (In the example below used a pink color to verify styles are applied.)
In this scenario, output is like this:
The css part:
.addPadding{
margin-bottom: 15px;
margin-left: 15px;
margin-right: 15px;
background-color: pink;
}
Code used:
setContent(addGridLayout())
////
private GridLayout addGridLayout(){
// Create a 4 by 4 grid layout.
GridLayout grid = new GridLayout(4, 4);
//grid.setSpacing(true);
grid.addStyleName("example-gridlayout");
// Fill out the first row using the cursor.
for (int i = 0; i < 4; i++) {
Label l=new Label("Col " +
(grid.getCursorX() + 1));
grid.addComponent(l);
grid.setComponentAlignment(l,Alignment.BOTTOM_CENTER);
}
// Fill out the first column using coordinates.
for (int i = 1; i < 4; i++) {
TextField x=new TextField();
x.addStyleName("addPadding");
grid.addComponent(x, 0, i);
}
// Fill out the secondcolumn using coordinates.
for (int i = 1; i < 4; i++) {
TextField x=new TextField();
x.addStyleName("addPadding");
grid.addComponent(x, 1, i);
}
// Fill out the third column using coordinates.
for (int i = 1; i < 4; i++) {
DateField x=new DateField();
x.addStyleName("addPadding");
grid.addComponent(x, 2, i);
}
// Fill out the third column using coordinates.
for (int i = 1; i < 4; i++) {
ComboBox x=new ComboBox<String>();
x.addStyleName("addPadding");
grid.addComponent(x, 3, i);
}
return grid;
}
if the columns have fixed width you could create 2 GridLayouts one for the header and one for the content. Both of them should have no margin and the layout that contains them should have no spacing.

conditional formatting not working

(am using PHPExcel 1.7.8)
I create a sheet and populate it with a table of numeric data. Then Excel refuses to apply conditional formatting of the 3-color-transition type to the numeric data.
That means, too:
1) I can use conditional formatting of the "top 10 values" kind
2) If I populate right next to the generated table few cells with numbers then I can use the cond formatting of transitional kind
3) If I copy two cells from the generated table somewhere else in a simple copy/paste fashion still can't use the transitional formatting
4) If I copy two cells from the generated table somewhere else using the "just the value"-pasting I do can use the transitional formatting
Another important observation here is, that when I select a cell of the generated table and click into the value bar - right at that moment - the cell changes its color to what it should be regarding the conditional formatting!
This is somewhat similar to another phenomena I observed with PHPExcel generated spreadsheets. Sometimes it happens that, when I double click into a cell to get into editing mode - the cell turns pit black. But still I can change the value.
There seems to be something wrong with how a cell is represented in the Excel-file I guess. Something related to the control of the coloring ... !?
I could of course copy/(value-)paste everything. But maybe I am just using PHPExcel the wrong way? Or there is a quick way to convert an Excel file at once in a useful way?
The full code I use is this:
$excelWorkbook = null;
if(file_exists($filename)) {
$reader = PHPExcel_IOFactory::createReader("Excel2007");
$excelWorkbook = $reader->load($filename);
} else {
$excelWorkbook = new PHPExcel();
}
$sheet = $excelWorkbook->getSheetByName($tabName);
if ($sheet !== null) {
$excelWorkbook->removeSheetByIndex($excelWorkbook->getIndex($sheet));
}
$sheet = new PHPExcel_Worksheet($excelWorkbook, $tabName);
$sheet = $excelWorkbook->addSheet($sheet);
$columns = array_keys($targetArray);
$rows = array_keys($targetArray[$columns[0]]);
for($i = 0; $i < count($columns); $i++){
$sheet->setCellValueByColumnAndRow($i+1,1,$columns[$i]);
}
for($i = 0; $i < count($rows); $i++){
$sheet->setCellValueByColumnAndRow(0,$i+2,$rows[$i]);
}
for($i = 0; $i < count($columns); $i++){
for($j = 0; $j < count($rows); $j++) {
$sheet->setCellValueByColumnAndRow($i+1, $j+2, $targetArray[$columns[$i]][$rows[$j]]);
}
}
$excelWorkbook->setActiveSheetIndex($excelWorkbook->getIndex($sheet));
$xlsx = new PHPExcel_Writer_Excel2007($excelWorkbook);
$xlsx->save($filename);
The workaround-type solution is to select all cells in the respective sheet and choose for background color 'none'.
Apparently the cells are colored white and this coloring overlays the conditional coloring.
This may be a bug due to the fact that for solid fills in cells Excel reverses the meaning of foreground and background colours but in conditional (dxf) formats it doesn't.
Or, to put it another way background and foreground are stored differently for cell and conditional formats.
I encountered this issue in the Perl Excel::Writer::XLSX module.

How to add a click Listener to a table's cell in vaadin?

I created a multiselectable table in vaadin, but I can't select only a cell in this table when I click it selects all row.
Is there any way of selecting only a cell of a row ?
The title of the question doesn't reflect the actual question inside
Is there any way of selecting only a cell of a row ?
No. The whole point of a Vaadin table is to reflect rows of data in a tabular form. Setting a table to selectable keeps track of the itemIds of the selected rows with the table
You might be able to simulate selecting cells by using a ColumnGenerator in the table, and adding a listener to the generated component. Removing the listener may be tricky, however.
Alternatively, you may wish to simply generate components in a GridLayout and keep track of the selected cells yourself.
Ultimately, the approach here really depends upon exacly what you are trying to achieve.
It depends on what you're trying to accomplish. (Your question title and your question details are addressing two different questions.) If you're wondering whether or not you can target a specific cell and add a click listener to it, then yes, of course you can:
//initial layout setup
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
//Create a table and add a style to allow setting the row height in theme.
final Table table = new Table();
table.addStyleName("components-inside");
//Define the names and data types of columns.
//The "default value" parameter is meaningless here.
table.addContainerProperty("Sum", Label.class, null);
table.addContainerProperty("Is Transferred", CheckBox.class, null);
table.addContainerProperty("Comments", TextField.class, null);
table.addContainerProperty("Details", Button.class, null);
//Add a few items in the table.
for (int i=0; i<100; i++) {
// Create the fields for the current table row
Label sumField = new Label(String.format(
"Sum is <b>$%04.2f</b><br/><i>(VAT incl.)</i>",
new Object[] {new Double(Math.random()*1000)}),
Label.CONTENT_XHTML);
CheckBox transferredField = new CheckBox("is transferred");
//Multiline text field. This required modifying the
//height of the table row.
TextField commentsField = new TextField();
//commentsField.setRows(3);
//The Table item identifier for the row.
Integer itemId = new Integer(i);
//Create a button and handle its click. A Button does not
//know the item it is contained in, so we have to store the
//item ID as user-defined data.
Button detailsField = new Button("show details");
detailsField.setData(itemId);
detailsField.addListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
// Get the item identifier from the user-defined data.
Integer iid = (Integer)event.getButton().getData();
Notification.show("Link " +
iid.intValue() + " clicked.");
}
});
detailsField.addStyleName("link");
//Create the table row.
table.addItem(new Object[] {sumField, transferredField,
commentsField, detailsField},
itemId);
}
//Show just three rows because they are so high.
table.setPageLength(3);
layout.addComponent(table);
It might be beneficial to examine the documentation.

Layout grid with images, labels, scrollview

I'm creating a layout for an iPad app that will consist of xx number of images and buttons(dynamically determined based on response from web service call) and I need to place them in a grid-like layout in a scroll view(horizontal)...
Now, I know that there are many custom UI Controls that can do something similar to this, but I haven't found one to match my 'needs'...
Basically what I want/need is that each 'entry' has an image, an overlay image, a button matching the size of the image and two labels on top of the image...
So does anybody know of a custom UI control that would match what I want?
Or do I have to write this from scratch?
I can potentially have as little as 10 entries, but also all the way up to 100+ (probably not a lot higher than this), so perhaps there is a more memory-friendly approach then what I'm considering below... - another issue is that I need to redo this every time the view appears(reason: I need to show updated data)...
I've done some initial testing of creating the grid manually, and have this so far:
int rows = 3; // fixed, will either be 2 or 3, depending on final size of images...
int columns = 8;// will be determined by response from web service
for(int i = 0; i < columns; i++)
{
for(int j = 0; j < rows; j++)
{
// Create the buttons to handle button press
UIButton *childButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
childButton.frame = CGRectMake(i * 100 + 10, j * 100 + 20, 100, 30);
[childButton setTitle:#"Test" forState:UIControlStateNormal];
[childButton addTarget:self action:#selector(presentPopoverMenu:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:childButton];
// Create the images to display the pictures of the children
// Create the labels to display child name
// Create the labels to display pick up time
}
}
I would suggest creating custom view... Create a custom class from UIView and put all those controls on it. You should probably create initWithCustomData where custom data is what you get from web. Once you have all that you can sort them anyway you want as if they were a single simple control.
As for updating. If the whole view has fixed size just create some inner methods in custom view to change frames of subviews. If frame is dynamic you basically do the same but you have to reposition all custom views (just use UIView animations).

How to avoid JQuery UI accordion with a long table inside from scrolling to the beginning when new rows are appended?

I have a table of many rows in a JQuery UI accordion.
I dynamically append the table this way:
var resJson = JSON.parse(connector.process(JSON.stringify(reqJson)));
for ( var i in resJson.entryArrayM) {
// test if entry has already been displayed
if ($("#resultTr_" + resJson.entryArrayM[i].id) == null)
continue;
$("#resultTable > tbody:last").append(listEntry.buildEntryRow(resJson.entryArrayM[i]));
}
Firstly I check if a row of the same tr id already exists. If not, I would append to the last row of the table.
It works. But the problem is: every time a row is appended, the accordion would scroll to the first row of the table. Since the table is remarkably long, it makes users inconvenient to scroll down again and again to watch newly-added rows. So how to avoid this?
First of all, just do one append rather than appending every time through the loop:
var resJson = JSON.parse(connector.process(JSON.stringify(reqJson)));
var seen = { };
var rows = [ ];
var trId = null;
for(var i in resJson.entryArrayM) {
// test if entry has already been displayed
var trId = 'resultTr_' + resJson.entryArrayM[i].id;
if($('#' + trId).length != 0
|| seen[trId])
continue;
rows.push(listEntry.buildEntryRow(resJson.entryArrayM[i]));
seen[trId] = true;
}
$("#resultTable > tbody:last").append(rows.join(''));
Also note that I corrected your existence test, $(x) returns an empty object when x doesn't match anything, not null. Not only is this a lot more efficient but you'll only have one scroll position change to deal with.
Solving your scrolling issue is fairly simple: find out what element is scrolling, store its scrollTop before your append, and reset its scrollTop after the append:
var $el = $('#whatever-is-scrolling');
var scrollTop = $el[0].scrollTop;
$("#resultTable > tbody:last").append(rows.join('')); // As above.
$el[0].scrollTop = scrollTop;
There might be a slight visible flicker but hopefully that will be lost in the noise of altering the table.
You could also try setting the table-layout CSS property of the <table> to fixed. That will keep the table from trying to resize its width or the width of its columns and that might stop the scrolling behavior that you're seeing. The downside is that you'll have to handle the column sizing yourself. But, you could try setting table-layout:fixed immediately before your append operation to minimize the hassle.

Resources