How to set row class dynamically in NGX datatable? - javascript

I am basically implementing a search functionality which is outside of the table, and want to highlight the rows if the search content matches something in the table row.
Also there are multiple tables on the page.
Here's my panel component.
<app-mystuff-dashboard-panel *ngFor="let group of initialGroupedSearchResults | objectFilter: { MyContentSetScope: 'Private', MyContentSetType : 'System', contentSetName: 'Clipboard' } | orderBy: 'contentSetName'"
[contentSet]="group"
[searchText]="searchText"></app-mystuff-dashboard-panel>
And in this above component I am running ngOnChanges, to get the searchText changes(which is a string)
I have tried using [rowClass]="getRowClass" in the ngx-dtatable input, but that function doesn't fire always, like how ngClass function changes everytime anything changes.
getRowClass(row) {
return _includes(row.DynamicProperties.myContentItemKey, this.searchText) ? 'yellowbackground' : 'bluebackground';
}
The row parameter in this function is undefined mostly. Also I have around 100 rows on around 3 tables, and this getRowClass funciton fires only around 5 times for 3 tables combined when the searchText changes..
I have tried re-rendering the table all over again onChange, that doesn't work as well.
if ((changes.searchText && (changes.searchText.currentValue !== changes.searchText.previousValue))) {
console.log(this.searchText);
this.items = this.items.slice();
this.items = [...this.items];
this.items.push({});
this.items.splice(-1, 1);1
this.items = [...this.items];
this.changeDetector.detectChanges();
}

Related

Make all filter options 'active' on initialisation - Angular

https://stackblitz.com/edit/timeline-angular-7-wbff3f
The above stackblitz will demo a few pipe filters. If you click on locations of "North, South or East", it will populate the *ngFor loop - these filters can be selected on/off and use a "multifilter pipe". By default I want all these filter buttons "active" or "on" to show the complete populated list to begin with, allowing you to then click the filters off. Otherwise, the list if blank on first load!
.html file
<button [class.active]="entry.isLocationActive" (click)="toggle(entry.location); entry.isLocationActive = !entry.isLocationActive" class="btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique">{{entry.location}}</button>
<my-timeline-entry *ngFor="let entry of timeLine | filter:filteredYear:'year'| multifilter:filteredLocations:'location' " timeEntryHeader={{entry.year}} timeEntryContent={{entry.detail}} timeEntryPlace={{entry.place}} timeEntryLocation={{entry.location}}></my-timeline-entry>
.ts file
filteredLocations: string[] = [];
toggle(location) {
let indexLocation = this.filteredLocations.indexOf(location);
if (indexLocation >= 0) {
this.filteredLocations = this.filteredLocations.filter((i) => i !== location);
} else {
this.filteredLocations.push(location);
}
}
I've played around with pre-populating the filteredLocations object with all the values, so it starts off with them all therefore active.
I managed to get the 'active' class to be active on first load but that did not carry through to the pipe filter. I'm sure its not a big change just can't see it, any help would be appreciated greatly!
filteredLocations = this.timeLine.map(a => a.location);
Adding this to the .ts file and replacing the empty filteredLocations: string[] = [];
I wasn't far off initially in the end. Hope it helps others.

Custom filter: can I have custom buttons for filter?

I am trying to have my own custom filter on ag-grid angular.
Apart from Apply button, I also want to have other buttons for the filter. i.e. if I can explain this in some sort of UI,
|--Custom Filter-------------------.
| Filter Text: _____________ |
| Apply | Clear | Clear All|
|_______________________|
By using default filter component of ag-grid, I know that I can have two buttons I need if I provide filterParams in ColDef.
filterParams: {
applyButton: true,
clearButton: true
}
But what about the other custom (Clear All) button? Is there any way I can achieve it?
Achieved it after few hours of search and trial-error.
Have a look at the example given here: ag-Grid Angular Custom Filter Component
Have a look at the PartialMatchFilterComponent and its code.
After some code updates for template and component, we can achieve it.
Update the template:
<button (click)="apply()">Apply</button>
<button (click)="clear()">Clear</button>
<!-- any other buttons you want to keep -->
Little update in the component code: Just need to call this.params.filterChangedCallback() on Apply button click.
apply(): void {
this.params.filterChangedCallback();
}
clear(): void {
this.text = '';
this.params.filterChangedCallback();
}
onChange(newValue): void {
if (this.text !== newValue) {
this.text = newValue;
// this.params.filterChangedCallback(); - remove
}
}

SAPUI5 TreeTable's getRows method returns empty array on the first call

I am trying to build an SAPUI5 application using TreeTable and I'm facing some problems to use its methods.
In my app, I have a button which triggers this method.
onChangeViewContext: function(oEvent) {
.........
.........
var aViewContext = oContext.oModel.getProperty(sPath + "/ViewContext");
var aDataModel = oContext.oModel.getProperty("/ApplicationCollection/" + sAppId + "/DataModel");
var oStructure = this._createParentChildStructure(aDataModel);
var oTreeModel = this.getView().getModel("treeModel");
oTreeModel.setData(oStructure);
this._oViewDetailLine = oSource.getParent().getParent().getParent();
this._oViewDetailLine.setVisible(false);
this.byId("idSelectElementsPanel").setVisible(true);
this._setSelectedItems(aViewContext, oTree);
}
What I'm trying to do here is only bind the rows with my treeModel, get tree table object and send it to my _setSelectedItems method which below.
_setSelectedItems: function(aViewContext, oTree) {
oTree.clearSelection();
var sElementName;
var aSelectedIndices = [];
var aElements = [];
var aRows = oTree.getRows();
aRows.forEach(function(row) {
if (row._oNodeState !== undefined) {
aElements.push(row.getCells()[0].getText());
}
});
I need to get rows array here because I will use it for setting selected items of tree table. The problem is when "onChangeViewContext" triggered, oTable.getRows() returns an empty array. But when I click cancel button (which just hides my tree table, nothing more) and then trigger "onChangeViewContext" function again, I can get the rows array completely.
Even on the first call when I try to get table's model, I can get the treeModel and its data correctly.
I've tried to refresh bindings, aggregations etc. But no luck.
By the way, I'm using row binding in my xml view like this :
<t:TreeTable id="idSelectElementsTree" rows="{path: 'treeModel>/'}" selectionMode="MultiToggle" enableSelectAll="false"
rowSelectionChange="onSelectElement">
I'm really drowning here so any any help would be appreciated.
Edit : rest of the setSelectedIndexes function :
aViewContext.forEach(function(name) {
sElementName = name;
if (aElements.indexOf(sElementName) !== -1) {
aSelectedIndices.push(aElements.indexOf(sElementName));
}
});
aSelectedIndices.forEach(function(idx) {
if (oTree.getRows()[idx]._bHasChildren) {
oTree.expand(idx);
}
oTree.addSelectionInterval(idx, idx);
});
What could help here is to add an event rowsUpdated="onRowsUpdated" to the table in the XML view. This event is triggered after the table has been loaded and will hence provide you with the data via;
this.getView().byId("sTableId").getRows();
The difference to your approach is that the event would not be triggered by the press of a button but automatically, as the table is rendered. You can then also use this function to trigger another one as per your use case.

Style a checkbox in datatable columns

I have a datatable from ajax source. I want to display a checkbox in one column based on its value.
If the value is active, checkbox should be checked, otherwise it remains unchecked.
I am using Switchery JS to stylize the checkbox. It works fine in normal HTML body, but not inside a datatable column.
Here is the fiddle:
https://jsfiddle.net/sohal/gfuuazxL/4/
The problem is that you are doing the Switchery' before the dataTable is populated with data. And even if you did it after, you would still end up not having Switcherys on hidden rows, i.e on page #2, #3 and so on.
So you must initialise Switchery after the dataTable is initialised and do the Switchery on all rows. You can do this in the initComplete() callback, and iterate over all rows by using the API every() method :
$(document).ready(function() {
var table = $('#datatable-buttons').DataTable({
initComplete : function() {
this.api().rows().every( function ( rowIdx, tableLoop, rowLoop ) {
this.nodes().to$().find('.js-switch').each(function(i, e) {
var switchery = new Switchery(e, {
color: '#26B99A'
})
})
})
},
...//rest of the options
})
})
forked fiddle -> https://jsfiddle.net/jpkysyp1/

label inside combobox and conditional multiselect

I am building a pretty combobox with checkboxes and conditional entries. Everything works out alright, except for two features that I cannot figure out how to implement.
1) I would like to move the label inside the combobox, make it shift the values to the right, and appear in a slightly gray color.
2) I would like the value to ignore certain entries (group headers) selected. Those entries are there for functionality only - to select/unselect groups of other entries.
The entire project is in the zip file. You don't need a server, it's a client base app. Just download the archive, unpack, and launch app.html in your browser.
http://filesave.me/file/30586/project-zip.html
And here's a snapshot of what I would like to achieve.
Regarding your second issue, the best way I see is to override combobox onListSelectionChange to filter the values you don't want:
onListSelectionChange: function(list, selectedRecords) {
//Add the following line
selectedRecords = Ext.Array.filter(selectedRecords, function(rec){
return rec.data.parent!=0;
});
//Original code unchanged from here
var me = this,
isMulti = me.multiSelect,
hasRecords = selectedRecords.length > 0;
// Only react to selection if it is not called from setValue, and if our list is
// expanded (ignores changes to the selection model triggered elsewhere)
if (!me.ignoreSelection && me.isExpanded) {
if (!isMulti) {
Ext.defer(me.collapse, 1, me);
}
/*
* Only set the value here if we're in multi selection mode or we have
* a selection. Otherwise setValue will be called with an empty value
* which will cause the change event to fire twice.
*/
if (isMulti || hasRecords) {
me.setValue(selectedRecords, false);
}
if (hasRecords) {
me.fireEvent('select', me, selectedRecords);
}
me.inputEl.focus();
}
},
And change your onBoundlistItemClick to only select and deselect items in the boundlist not to setValue of the combo:
onBoundlistItemClick: function(dataview, record, item, index, e, eOpts) {
var chk = item.className.toString().indexOf('x-boundlist-selected') == -1;
if ( ! record.data.parent) {
var d = dataview.dataSource.data.items;
for (var i in d) {
var s = d[i].data;
if (s.parent == record.data.id) {
if (chk) { // select
dataview.getSelectionModel().select(d[i],true);
} else { // deselect
dataview.getSelectionModel().deselect(d[i]);
}
}
}
}
},
Regarding your first issue, it is easy to add the label using the displayTpl config option. But this will only add the text you need, without any style (grey color, etc). The combo is using a text input, which does not accept html tags. If you don't need the user to type text, than you may want to change the combo basic behavior and use another element instead of the text input.

Categories