Set new column definition by setColumnDefs doesn't work anymore - ag-grid

I'm trying to set new column definitions by calling setColumnDefs using the grid API. This doesn't work as expected. The names of the column headers will not be updated anymore!
See this Plunkr: Version 19.1.x
Version 19.0.0 is latest working version.
See this Plunkr: Version 19.0.0
For me it seems to be a bug!?
In my project I'm using Angular 5 and I notice the same behaviour.

I was able to reproduce your behaviour. The following (dirty) workaround works:
gridOptions.api.setColumnDefs([]);
gridOptions.api.setColumnDefs(newColDefs);
Setting the columnDefs to an empty array and then passing the newColDefs seems to achieve what you are looking for.

I suppose it up to the new way of change-detection on the latest version.
If you will update your code like that:
function updateColDef()
{
let data = [];
columnDefs.forEach(function(colDef) {
colDef.headerName = colDef.headerName + ' X ';
data.push(colDef);
})
data.push( {
headerName: 'New Column',
});
gridOptions.api.setColumnDefs(data);
}
It will work as expected.
Update:
When new columns are set, the grid will compare with current columns and work out which columns are old (to be removed), new (new columns created) or kept (columns that remain will keep their state including position, filter and sort).
Comparison of column definitions is done on 1) object reference comparison and 2) column ID eg colDef.colId. If either the object reference matches, or the column ID matches, then the grid treats the columns as the same column.
In the first case, it was an object comparison, on the second sample (after update) its colId case.
changes came from 19.1 version release
AG-1591 Allow Delta Changes to Column Definitions.

Related

Why is Arrayformula returning only the first row

Update: sample sheet provided here: https://docs.google.com/spreadsheets/d/1BapXdaVOUL634SstNJXqYNocsD_EvvtlbJ77vlElmZs/edit?usp=drivesdk. Any help will be appreciated!
Hi fellow nerds.
I'm trying to make the current column (most recent interaction date with client) display the max values (most recent dates) from ContactLog!b:b (dates of all recorded interactions), when the client name in ContactLog!A:A matches to the client name in current row column A.
After many days of trying, I've found several formulas to successfully achieve this result for the current cell only.
=MAXIFS(ContactLog!B:B, ContactLog!A:A, A:A)
=MAX(FILTER(ContactLog!B4:B, ContactLog!A4:A=VLOOKUP(A2, ContactLog!A4:B, 1, FALSE)))
=MAX(QUERY(ContactLog!A4:B, ""SELECT B WHERE A = '""&VLOOKUP(A2, ContactLog!A4:B, 1, FALSE)&""'"", 0))
=IF(COUNTIF(ContactLog!A:A, A2),MAX(FILTER(ContactLog!B:B, ContactLog!A:A = A2)),"")
But none of these seem to work with arrayformula, to spread to the entire column. I'd like this result to apply automatically to the entire column (wherever column A is not blank).
It's displaying the correct max value for the first cell (in which the formula is written), and I could drag the formula down, but not spreading automatically as an array.
I've tried using =match with =filter, but that keeps running into mismatched range row sizes. (I've previously solved that by using filter within a filter, but can't figure that out here).
[I have a similar issue for the nearby columns also, "most recent interaction method", and "reminders & goals". The formula there is:
=INDEX(ContactLog!C:C, MATCH(MAX(IF(ContactLog!A:A=A2, IF(ContactLog!B:B=MAX(IF(ContactLog!A:A=A2, ContactLog!B:B)), ROW(ContactLog!B:B)))), ROW(ContactLog!B:B), 0))
And
=IFERROR(CONCATENATE(JOIN(" • ",FILTER(ContactLog!D:D,ContactLog!A:A=A2, ContactLog!D:D<>"")),IF(INDEX(ContactLog!D:D,MAX(IF(ContactLog!A:A=A2,ROW(ContactLog!D:D))))="","","")),"")
They both work great, but I can't get them to work with arrayformula...]
What am I missing?
You can do something like this with BYROW, that allows you to expand your formula through the column and be calculated "row by row". Using your first option:
=BYROW(A:A, LAMBDA (each,IF(each="","",MAXIFS(ContactLog!B:B, ContactLog!A:A, each))))

SAPUI5 Variant key on Save strange behaviour

I am trying to implement a Variant management in SAPUI5 using Personalization service of sap.ushell.Container. I have written functions to Save, Manage(delete, rename) and select Variants from the drop down. However i see strange behavior when i select a variant in the method mentioned below.
onSelectVariant: function (oEvent) {
var sSelectedVariantKey = oEvent.getParameter('key');
Assume i have existing variants 'A1', 'A2' and 'A3'.
When i SaveAs a new variant with new values (lets call it 'X1'), the new variant is created. Then i select another already existing variant from dropdown( A1 or A2 or A3), i see the corresponding values. Now i again select the newly created variant X1 but i don't see the new values.
When i debug the above mentioned method, i see that for all the existing variants, the oEvent.getParameter('key') returns the variant indexs like 0,1,2,3 etc. but for the newly created variant X1, it returns the value 'sv1579082806311' and hence it doens't find it in variantset
oPersonalizationVariantSet.getVariant(sVariantKey)
and then it doesn't show the new values.
If i run the program again, i see that previously created variant X1 now shows correct values as the method oEvent.getParameter('key') returns the index and not 'sv....'. but if i now create a new variant X2, the same issue happens with X2.
I am running the App on cloud WebIDE and not on the FIORI launchpad.
Can someone help me what may be going wrong while saving the variant ?
Thanks
Br
Nilesh Puranik
I had the exact same issue recently. I assume that this is a bug in the VariantManagement control. You could create an Issue in the openui5 github project.
I also had this problem and came to the conclusion its a bug in VM control. It gives a new and long key to a newly saved variant. In the oEvent parameter "key" of your onSelect function you will see this new key.
I soved the issue by adding a new property to my JSON object I bound for variants.
In Variant Save event:
tableModel.oData.tabVariants.push({key: VariantParam.key,
text: VariantParam.name,
newKey:this.oVariant.getVariantKey()})
Then in variant select event:
var selectedKey = oEvent.getParameter("key");
var variant = this.woTableSet.getVariant(selectedKey);
if(!variant){
//In this case its a newly created variant with an internal key
//This is a workaround for the key confusion in variants
selectedKey = tableModel.oData.tabVariants.find(t => t.key ===
selectedKey).newKey;
variant = this.woTableSet.getVariant(selectedKey)
if(!variant){return} //then I give up
}
You need replace the auto generated key by variant key:
const autoGeneratedKey = oEvent.getParameters().key;
this.oContainer.save().done(function (cb) {
const oVM = that.getView().byId("vm");
oVM.replaceKey(autoGeneratedKey, that.oVariant.getVariantKey());
oVM.setInitialSelectionKey(that.oVariant.getVariantKey());
});

NatTable Filter using Regex

I am interested in using regular expressions in the NatTable filter. I have set up my code based on the following helpful links:
http://www.vogella.com/tutorials/NatTable/article.html#exercise-adding-a-filter-functionality-to-a-nattable
https://www.eclipse.org/forums/index.php/t/1069806/
From what I can gather, it basically boils down to adding the following code to your existing Filter:
FilterRowHeaderComposite<T> filterRowHeaderLayer = new
FilterRowHeaderComposite<>(filterStrategy,
sortHeaderLayer, columnHeaderDataLayer.
getDataProvider(), configRegistry);
int rowNum = 2;
configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR,
new FilterRowTextCellEditor(), DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + rowNum);
configRegistry.registerConfigAttribute(FilterRowConfigAttributes.
TEXT_MATCHING_MODE, TextMatchingMode.REGULAR_EXPRESSION,
DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + rowNum);
configRegistry.registerConfigAttribute(CellConfigAttributes.
DISPLAY_CONVERTER, new FilterRowRegularExpressionConverter(),
DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + rowNum);
The filtering seems to work in certain situations and not others. For example, assume I have a cell that has the data "This is a Test". If I use the expression *t, it will find the row (which is what I expect). If I use the expression *x, it will not find the row (which is what I expect). If I use the expression ^(123) it will not find the row (which is NOT what I expect). Am I doing something incorrect?
Thanks!
I think the issue is in the regular expression. It seems that the cardinality is missing. Using [^123]* it works as you expect it.
If you for example test the _6031_GlazedListsFilterExample and insert [^abc] for the Housenumber column, you will see all entries that have only a one digit value. Adding the * all rows appear.

dataFrame keying using pandas groupby method

I new to pandas and trying to learn how to work with it. Im having a problem when trying to use an example I saw in one of wes videos and notebooks on my data. I have a csv file that looks like this:
filePath,vp,score
E:\Audio\7168965711_5601_4.wav,Cust_9709495726,-2
E:\Audio\7168965711_5601_4.wav,Cust_9708568031,-80
E:\Audio\7168965711_5601_4.wav,Cust_9702445777,-2
E:\Audio\7168965711_5601_4.wav,Cust_7023544759,-35
E:\Audio\7168965711_5601_4.wav,Cust_9702229339,-77
E:\Audio\7168965711_5601_4.wav,Cust_9513243289,25
E:\Audio\7168965711_5601_4.wav,Cust_2102513187,18
E:\Audio\7168965711_5601_4.wav,Cust_6625625104,-56
E:\Audio\7168965711_5601_4.wav,Cust_6073165338,-40
E:\Audio\7168965711_5601_4.wav,Cust_5105831247,-30
E:\Audio\7168965711_5601_4.wav,Cust_9513082770,-55
E:\Audio\7168965711_5601_4.wav,Cust_5753907026,-79
E:\Audio\7168965711_5601_4.wav,Cust_7403410322,11
E:\Audio\7168965711_5601_4.wav,Cust_4062144116,-70
I loading it to a data frame and the group it by "filePath" and "vp", the code is:
res = df.groupby(['filePath','vp']).size()
res.index
and the output is:
[E:\Audio\7168965711_5601_4.wav Cust_2102513187,
Cust_4062144116, Cust_5105831247,
Cust_5753907026, Cust_6073165338,
Cust_6625625104, Cust_7023544759,
Cust_7403410322, Cust_9513082770,
Cust_9513243289, Cust_9702229339,
Cust_9702445777, Cust_9708568031,
Cust_9709495726]
Now Im trying to approach the index like a dict, as i saw in examples, but when im doing
res['Cust_4062144116']
I get an error:
KeyError: 'Cust_4062144116'
I do succeed to get a result when im putting the filepath, but as i understand and saw in previouse examples i should be able to use the vp keys as well, isnt is so?
Sorry if its a trivial one, i just cant understand why it is working in one example but not in the other.
Rutger you are not correct. It is possible to "partial" index a multiIndex series. I simply did it the wrong way.
The index first level is the file name (e.g. E:\Audio\7168965711_5601_4.wav above) and the second level is vp. Meaning, for each file name i have multiple vps.
Now, this is correct:
res['E:\Audio\7168965711_5601_4.wav]
and will return:
Cust_2102513187 2
Cust_4062144116 8
....
but trying to index by the inner index (the Cust_ indexes) will fail.
You groupby two columns and therefore get a MultiIndex in return. This means you also have to slice using those to columns, not with a single index value.
Your .size() on the groupby object converts it into a Series. If you force it in a DataFrame you can use the .xs method to slice a single level:
res = pd.DataFrame(df.groupby(['filePath','vp']).size())
res.xs('Cust_4062144116', level=1)
That works. If you want to keep it as a series, boolean indexing can help, something like:
res[res.index.get_level_values(1) == 'Cust_4062144116']
The last option is a bit less readable, but sometimes also more flexibile, you could test for multiple values at once for example:
res[res.index.get_level_values(1).isin(['Cust_4062144116', 'Cust_6073165338'])]

Maintain DataRowState in ADO.NET Dataset - RejectChanges() method does not work?

The problem simplified:
I have a DataSet with some datatables...
I have a Winforms DataGrid bound to one of the datatables.
User sticks some rows into said datatable, via the DataGrid, let's say 3 rows;
All three rows now have their RowState = DataRowState.Added.
I now begin a sqlserver transaction.
Then call dataAdapter1.Update(dataSet1) to update rows into SqlServer.
row 1.. OK
row 2.. OK
row 3.. error at the sqlserver level (by design i enforced a unique index)
Upon detecting this error, i Rollback the sqlserver transaction.
I also try to "rollback" the datatable / dataset changes, using either of Dataset1.RejectChanges() and / or Datatable1.RejectChanges().
Problem is neither of .RejectChanges() work the way i envisaged. My datatable now has two rows (row1, row2), whose RowState = DataRowState.Unchanged; row3 has disappeared altogether.
What i want to happen is, when i roll back the sqlserver transaction, for all 3 rows in the datatable to remain in the SAME STATE just prior to the call to dataAdapter1.Update() method.
(Reason is so that the user can look at the error in the bound DataGrid, take corrective action, and attempt the Update again).
Any ideas anyone? i.e. i am looking for something equivalent to rolling back the state at the ADO dataTable level.
Ok, so i figured a way to get around this.
Get a clone of the original datatable, and update the clone.
If an error occurs, you still have the original datatable, with its original DataRowState; Furthermore, you can copy any errors that occur in the clone to the original Datatable, thus reflecting the errors in the datagrid for the user to see.
If update is successful, you simply refresh the original datatable with the clone.
VB Code:
Try
'daMyAdapter.Update(dsDataset, "MyDatatable") <-- replace original with below lines.
_dtMyDatatableClone = dsDataset.MyDatatable.Copy()
If _dtMyDatatableClone IsNot Nothing Then
daMyAdapter.Update(_dtMyDatatableClone)
'if you get here, update was successul - refresh now!
dsDataset.MyDatatable.Clear()
dsDataset.MyDatatable.Merge(_dtMyDatatableClone, False, MissingSchemaAction.Ignore)
End If
Catch
'uh oh, put error handler here.
End Try
I had a similar issue with trying to rollback changes to a DataTable that was bound to an Xceed DataGrid. Once the edits were made in the DataGrid, the edited values all become part of the DataRow's Current state. RejectChanges is only applicable for preventing the Proposed row state from becoming Current.
In order to revert the changes for a given row, I wrote a method to overwrite the current row version with the original version. In order to set a version as the Original, you simply call AcceptChanges() on the datatable.
public static void RevertToOriginalValues(DataRow row)
{
if (row.HasVersion(DataRowVersion.Original) && row.HasVersion(DataRowVersion.Current))
{
for (int colIndex = 0; colIndex < row.ItemArray.Length; colIndex++)
{
var original = row[colIndex, DataRowVersion.Original];
row[colIndex] = original;
}
}
}