How to reorder columns in datatable with drag and drop Primefaces - events

I use primefaces version 5.2 and jsf version 2.2.6.
I have a datatable and I want to reorder the columns with drag and drop. Besides I have also the column toggle functionality, with which I can hide columns. The reordering and hiding of columns are saved into the database.
For me it is no problem if on specific positions are hidden columns, I can drop the dragged column after or before the position of the hidden ones.
I use the following ajax event:
<p:ajax event="colReorder" listener="#{transactionsPage.onColumnReorder}"/>
and the method signature looks like this:
public void onColumnReorder(AjaxBehaviorEvent event)
If I could have used ReorderEvent to get the fromIndex and toIndex, it would have been very easy to deal with this situation, but unfortunately this event can be used only for dragging and dropping rows and not columns.
Is there a way to find out these indexes? Even only the fromIndex could be enough.

I managed to find a solution, maybe it can be helpful for someone in the future.
Because I didn't find indexes for fromIndex and toIndex for reordering the columns(there are only such indexes for reordering rows, which work with the ReorderEvent), I get the datatable from the AjaxBehaviorEvent and from that I get the columns and overwrite these indexes of the reordered columns in the database columns and then I can restore the view later with the reordered columns.
The code for triggering the event from the xhtml page looks like this:
<p:ajax event="colReorder" listener="#{transactionsPage.onColumnReorder}"/>
The code for the managed bean looks like this:
public void onColumnReorder(AjaxBehaviorEvent event) {
DataTable table = (DataTable) event.getSource();
List<ViewAttributes> allViewAttributesList = loadAllViewAttributes();
for (int i = 0; i < table.getColumns().size(); i++) {
UIComponent colComponentDestination = (UIComponent) table.getColumns().get(i);
//allViewAttributes is the list of columns from the database, in which I set the new indexes
for (int j = 0; j < allViewAttributesList.size(); j++) {
ViewAttributes viewAttrSource = allViewAttributesList.get(j);
if (viewAttrSource.getColumnName().equals(colComponentDestination.getId()) && i != viewAttrSource.getPosition()) {
viewAttrSource.setPosition(new Long(i));
//save column with new index in the database
getServiceManager().getViewService().getViewDao().update(viewAttrSource);
}
}
}
}

Related

Infragistics UltraGrid Group Changed Event

I have an Infragistics UltraGrid and I need to know when the user adds/removes a column grouping. I see there are events for when a row is collapsed/expanded and an event for when the grid's filter changes, but I don't see any events that would fire when a column grouping is added/removed. Does anyone know of an UltraGrid event that would fire at that point? If not, are there any workarounds I might be able to use to achieve this?
I've already tried using AfterBandHiddenChanged and AfterGroupPosChanged. Neither of those seem to do what I need.
I'm using Infragistics 11.2 CLR2.0 (I know it's quite out-of-date, but it's not my call to update it)
After some digging and experimenting, I found a workaround. It's not the prettiest, but it gets the job done. If anyone has any better suggestions, I'm all ears. But here's what I came up with in case someone else is interested.
I utilize the grid's BeforeSortChanged and AfterSortChanged events. The "Before" event sets a flag to indicate whether the groupings have changed. The "After" event is where I perform the operation I need to perform if the flag was set to indicate that the groupings changed.
Here's the "Before" event:
private void Grid_BeforeSortChange(object sender, Infragistics.Win.UltraWinGrid.BeforeSortChangeEventArgs e) {
int preSort = 0;
int postSort = 0;
// This set of sorted columns are the columns that were already sorted
// before the sort change.
foreach (var col in e.Band.SortedColumns) {
if (col.IsGroupByColumn) {
preSort++;
}
}
// This set of sorted columns are the columns that will be
// sorted after the sort change is applied
foreach (var col in e.SortedColumns) {
if (col.IsGroupByColumn) {
postSort++;
}
}
// Compare the number of grouped columns before the
// sort to the number after the sort
_groupingsChangedFlag = preSort != postSort
}
And here's the "After" event:
private void Grid_AfterSortChange(object sender, Infragistics.Win.UltraWinGrid.BandEventArgs e) {
if (!_groupingsChangedFlag) {
return;
}
// Groupings changed, so do some action
}

How to count total Local Data rows for Data Driven testing and then perform a function on a particular row?

I'm writing test automation scripts that is based on Data Driven testing for Web Browser test. I'm using Local Data as my data source.
Eg: Local Data table contains 2 rows and 2 columns for Username and Password.
I'm wondering is there is a way to perform a row "Count" function for the Local Data table.
And then,if the row count is two, perform a specific function.
The idea is something like this :
if LocalData.Row = 2 then
//Execute a function
else
//Close Browser
I can't seem to find any resources in the net for this. I'm just being introduced to Telerik so i'm learning as it goes and i'm really hoping you guys can help to give some pointers on this question.
Many many thanks in advance :)
Column and row are two different things.
When accessing the column by the RAD_Grid.MasterTableView.Columns.
You will be able to modify all the properties of a column. Like :
FilterDelay, CurrentFilterFunction, ShowFilterIcon, DataField, UniqueName, Display, Exportable...
foreach (GridColumn column in RAD_Grid.MasterTableView.Columns)
{
if (column is GridBoundColumn)
{
GridBoundColumn boundColumn = column as GridBoundColumn;
boundColumn.CurrentFilterValue = string.Empty;
}
}
To iterate through the row, on the data bound:
protected void Unnamed_DataBound(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
GridDataItem item = (GridDataItem)e.Item;
// LOGIC
}
//Total Item Count:
if (e.Item is GridPagerItem)
{
int itemsCount = ((GridPagerItem)e.Item).Paging.DataSourceCount;
}
}
Or
GridItemCollection gridRows = RAD_Grid.Items;
int i;
foreach (GridDataItem data in gridRows)
{
i++;
ItemClass obj = (ItemClass)data.DataItem;
}
As its not really clear what you want I will give you an other way around.
In your grid put a templated Column. I' am pretty sure that's what you are looking for. And if the logic is complexe put it in a function in code behind and simply :
<asp:Label ID="lbl_Exmpl" runat="server"
Text=' <%# MyFunction( Convert.ToInt32(Eval("Mydata")) ) %>' />

JavaFX8: Strings are not displayed in TableView

I have the following problem: I try to populate a tableview in JavaFX8 with an array. So, I try to add the array as a row to the tableview. I run this code in the Controller of my FXML file, when enter is pressed. This is the code:
String[] words = {"ace", "boom", "crew", "dog", "eon"};
List<String> tableViewRow = Arrays.asList(words);
ObservableList<String> row = FXCollections.observableList(tableViewRow); //observableArrayList also doesn't work
transactionOverview.getItems().add(row);
transactionOverview is my tableview, and the String[] is just a placeholder for my actual String[]. I tried to create my tableview in multiple ways:
public TableView<ObservableList<String>> transactionOverview;
public TableView<ObservableList> transactionOverview;
public TableView transactionOverview;
None of them works.
The problem is that tableview gets an extra row, which I can select, but there are now string values visible in the tableview. I don't know if they are added.
My code is based on Javafx 2.2 - Dynamic table view - table data (answer from Jitendra Pareek), and I have chosen for this solution because I don't want to use an extra class to populate my tableview.
Any help is appreciated!
Since (according to your comments) you have a fixed number of columns, I would strongly recommend creating a model class to hold the items in each row of the table. You can then follow the standard patterns and it should work readily.
However you manage a TableView, you must provide a cell value factory for each column. This is essentially a function that specifies how to get the value for a cell from the item in the row. If your use a model class that uses JavaFX properties, then you can use a PropertyValueFactory (though Java 8 lambda expressions make that pretty much redundant). Otherwise, you need to implement a callback.
If you really want to use a list structure to hold the data for each row, and assuming your table and table columns are all defined in the FXML file, you would do something like this in your controller class:
#FXML
private TableView<ObservableList<String>> transactionOverview ;
// ...
public void initialize() {
for (int i=0; i < transactionOverview.getColumns().size(); i++) {
TableColumn<ObservableList<String>, String> col = transactionOverview.getColumns().get(i);
final int colIndex = i ;
col.setCellValueFactory( (CellDataFeatures cellData) -> {
ObservableList<String> rowData = cellData.getValue();
return new ReadOnlyStringWrapper(rowData.get(colIndex));
});
}
// ...
}

Primefaces datatable sort order

I am using primefaces' datatable component to display a list of classes 'Student' which is something like :
class Student {
String firstName
String lastName
....
}
I populate the list form a native query. The datatable component is as follows :
<p:dataTable id="studentList" var="student" rowIndexVar="rowIndex"
value="#{studentBean.studentList}"
rowKey="#{student.firstName}" widgetVar="sList"
sortBy="#{student.firstName}" sortOrder="ASCENDING">
And I have a button which would basically refresh the data in the table. The problem is, when I refresh the data, the sorting order is all lost. How can I retain the sorting order?
The problem is that sorting is only applied just when you click the sorting icon. As a work around you can call some methods in datatable component to, first know what the last "sorted by column" and the you can use the primefaces datatable sorting feature. This will force the datatable to do the sorting whenever you want:
/**
* This code will first find what is the current order and the apply the sorting process to data.
* It is implemented looking at primefaces code and doing exactly the same steps on sorting (like default database sort)
* and decide what is the current order (like in column rendering to decide what is the column arrow style).
*/
protected void refrestTableComponentOrder(DataTable table) {
FacesContext facesContext = FacesContext.getCurrentInstance();
//When view is not created, like on first call when preparing the model, table will not be found
if(table == null){
return;
}
ValueExpression tableSortByVe = table.getValueExpression("sortBy");
String tableSortByExpression = tableSortByVe.getExpressionString();
//Loop on children, that are the columns, to find the one whose order must be applied.
for (UIComponent child : table.getChildren()) {
Column column = (Column)child;
ValueExpression columnSortByVe = column.getValueExpression("sortBy");
if (columnSortByVe != null) {
String columnSortByExpression = columnSortByVe.getExpressionString();
if (tableSortByExpression != null && tableSortByExpression.equals(columnSortByExpression)) {
//Now sort table content
SortFeature sortFeature = new SortFeature();
sortFeature.sort(facesContext, table, tableSortByVe, table.getVar(),
SortOrder.valueOf(table.getSortOrder().toUpperCase(Locale.ENGLISH)), table.getSortFunction());
break;
}
}
}
}
You can find the datatable component anywhere by calling:
FacesContext facesContext = FacesContext.getCurrentInstance();
DataTable table = (DataTable)facesContext.getViewRoot().findComponent(":YOUR_TABLE_CLIENT_ID");

Exporting a filtered Grid data In Telerik RadGrid

When exporting a rad grid data if the user has it filtered in any way the grid should just export the filtered data not the entire dataset - Any idea how to achieve this?
Regards - Hemant
Here is a solution that allows one to get a filtered, sorted list of data items using the current filter and sort settings from a Telerik RadGridView control (Silverlight version).
using Telerik.Windows.Data;
.
.
.
IEnumerable<MyClass> itemsToDisplay { get; set; } //The RadGridView is bound to this property
public void DoSomethingWithFilteredAndSortedDisplayItems(RadGridView rgv)
{
IQueryable<MyClass> iqItems = itemsToDisplay.AsQueryable();
FilterDescriptorCollection filter = rgv.FilterDescriptors;
SortDescriptorCollection sort = rgv.SortDescriptors;
List<MyClass> fsItems = iqItems.Where(filter).Sort(sort).ToIList() as List<MyClass>;
if (fsItems != null && fsItems.Count > 0)
{
DoSomethingWithDisplayItems(fsItems);
}
}
public void DoSomethingWithDisplayItems(IEnumerable<MyClass> list)
{
... //Do something
}
I think that if you assign the filtered set of data to the grid before calling the export method (which internally rebinds it), you will get the filtered values in the exported file.

Resources