Angular Slickgrid | How to Enable/Disable checkbox dynamically (Not show/hide checkbox) - javascript

export class Example1 implements OnInit {
prepareGrid() {
this.gridOptions = {
enableRowSelection: true,
enableCheckboxSelector: true,
checkboxSelector: {
// you can override the logic for showing (or not) the expand icon
// for example, display the expand icon only on every 2nd row
selectableOverride: (row: number, dataContext: any, grid: any) => (dataContext.id % 2 === 1)
},
multiSelect: false,
rowSelectionOptions: {
// True (Single Selection), False (Multiple Selections)
selectActiveRow: true,
},
};
}
}
We can use enableCheckboxSelector to show/hide checkbox. But how to enable/disable checkbox based on some condition dynamically ?

The question is already answered in the Wiki documentations, you can use selectableOverride, refer to Row Selection - Wiki, but it seems that you already have that code, or maybe you didn't understand what that was for?
If you want to change the selected row(s) at any point in time, then simply use the built-in SlickGrid method setSelectedRows(rowIndexes) which requires an array of row indexes, passing an empty array will clear all selections.
<angular-slickgrid
gridId="grid4"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[dataset]="dataset"
(onAngularGridCreated)="angularGridReady($event)"> <!-- <<== you need this line !-->
</angular-slickgrid>
angularGridReady(angularGrid: AngularGridInstance) {
this.angularGrid = angularGrid;
}
changeRowSelection() {
angularGrid.slickGrid.setSelectedRows(rowIndexes);
}

Related

FancyTree w/ ExtPersist - If no LocalStorage value for expanded, set defaults

I inherited some code and I've been asked to add a new 'feature'. The existing code sets the expanded state to 'true' for all top-level nodes not named "Favorites", but the "fancytree-1-expanded" Value in LocalStorage is not set until the user explicitly collapses and expands another top-level node. I understand that this is the expected behavior, but I need to bypass this and set the "fancytree-1-expanded" LocalStorage Value is none exists (I know the values of the top-level nodes, so I can name them easily).
Here is my FancyTree init code with persist (and several remarks I've used to try to identify the data and get this going):
// start of UI integration
buildMenu = function() {
$("#" + Menu).fancytree({
extensions: ["filter", "glyph", "persist"],
quicksearch: true,
//debugLevel: 4,
source: getandformatdata,
filter: {
autoApply: true, // Re-apply last filter if lazy data is loaded
autoExpand: true, // Expand all branches that contain matches while filtered
counter: true, // Show a badge with number of matching child nodes near parent icons
fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
hideExpandedCounter: true, // Hide counter badge if parent is expanded
hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
highlight: true, // Highlight matches by wrapping inside <mark> tags
leavesOnly: true, // Match end nodes only
nodata: true, // Display a 'no data' status node if result is empty
mode: "hide" // "dimm" = Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
},
glyph: {
preset: "awesome4",
map: {
expanderClosed: "expandIconSidebar",
expanderLazy: "expandIconSidebar",
expanderOpen: "expandedIconSidebar",
}
},
click: function (event, data) {
//needed to reapply classes
/*if($(data.originalEvent.target).hasClass('fancytree-expander')) {
//cannot apply class if not expanded
data.node.setExpanded(true);
//Add leaf node classes
$('.fancytree-node:not(.fancytree-folder)').closest('li').addClass('leafNode');
$('.fancytree-folder').closest('li').addClass("folderNode");
data.node.setExpanded(false);
}*/
if(data.node.isFolder()) {
//if(data.node.title==='Favorites') {
// $('#actGoHome').click();
//}
//else
return;
}
},
persist: {
store: "auto" // 'cookie', 'local': use localStore, 'session': sessionStore
},
postProcess: function (event, data) {
//if persist is not set then expand all folders except Favorite
//console.log("postdata", data);
//console.log("persist",$.ui.fancytree.getTree('#' + Menu).getPersistData());
let persistExpanded = $.ui.fancytree.getTree('#' + Menu).getPersistData().expanded[0];
//console.log("Expanded: "+persistExpanded);
let foldersExpanded = data.response.filter(d => { return persistExpanded.split("~").some(f => {return d.title === f})});
//console.log("foldersExpanded", foldersExpanded);
if (foldersExpanded.length == 0) {
data.response.forEach((d) => {
if (d.title != 'Favorites') {
d.expanded = true;
}
})
}
},
});
}
I've tried to look at using localStorage.getItem/setItem, but my site is in an iframe in another port from the parent app/site. This appears to be problematic for trying to directly get and set the LocalStorage, so I'm hoping to edit my FancyTree's ExtPersist code to set the LocalStorage value if none exists.
The following JSFiddle can be used if someone knows of a way to default in the Value for "fancytree-1-expanded" of "b9052f9a-1c45-47ef-9d66-8c2bded1230e~tr" if no Value exists - https://jsfiddle.net/vt8mrLt0/1/

How to change styling of cells that has been edited in ag-Grid?

I want to mark cells who has been edited so the user can see which cells have been touched and altered. I know there is a cell flash option, but that just changes the background colors for a bit. What I want is a background color change when an edit has been done.
Cannot seem to find any specific documentation on accessing for example the html element or the styling of affected cell.
Anyone got any ideas?
You can use ColDef.onCellValueChanged to detect if something changes and update the cell style accordingly using GridApi.refreshCells()
const columnDefs = [{
headerName: "Athlete",
field: "athlete",
onCellValueChanged: this.markAsDirty
},...]
...
private markAsDirty(params: ICellRendererParams) {
params.colDef.cellClass = (p) =>
p.rowIndex.toString() === params.node.id ? "ag-cell-dirty" : "";
params.api.refreshCells({
columns: [params.column.getId()],
rowNodes: [params.node],
force: true // without this line, the cell style is not refreshed at the first time
});
}
In your css file
:host ::ng-deep .ag-cell-dirty {
background-color: rgba(255, 193, 7, 0.5) !important;
}
You may also want to use defaultColDef if you want this behavior applied to all columns
this.gridOptions = {
defaultColDef: {
editable: true,
onCellValueChanged: this.markAsDirty
},
};
Live Demo
I did this on a project I was working on.
There is a cellClass property that you can define in your column definitions (https://www.ag-grid.com/javascript-grid-cell-styles/) and it can take a callback function with params: CellClassParams.
So try doing:
cellClass: (params: CellClassParams) => {
// you need to have a handle on the original untouched data
// See if the original value does not equal the modified value in params
// For shortness, I will write pseudocode
if (originalValue !== modifiedValue) {
return 'ag-cell-was-modified';
}
}
If many columns are editable, you may want to use a re-usable function for cellClass for each column.
That should apply the class ag-cell-was-modified conditionally whether the cell was modified or not and in your style.scss or main stylesheet, you can add:
.ag-cell-was-modified {
background: red;
}
Of course, if you are using SASS, you can place this class definition in somewhere more appropriate.

Non editable kendo grid ID

I'm new using kendo grid UI, i'm trying to make a non editable column (when updating) using a simple code :
schema: {
id: 'ID',
fields: {
id: { editable: false }
}
}
This default schema, makes by default non editable id column, and i can't even create a new row with id .
I want to make it non editable (when updating) but i want the possibility to create a row and assign an id from user (when creating).
Any ideas ?
Edit :
PS : the proprety is not related to only id, it can be on every column (can't update but can create)
The editable required a function instead of a value.
columns: [
{ field: 'value', editable: function () { return false; } }
],
Checkout here:
https://dojo.telerik.com/oROJayAd
I always doubt about that model editable option. It never really worked for me. It should have something very deep in the setup to make it work which I never realized what it. So this is a way to acomplish what you need that I know it indeed works: To cancel the edit event. Check it out:
edit: function(e) {
// Cancels a new row
if (arguments, e.model.isNew()) {
this.cancelRow(e.container.parent());
}
else { // Cancels a cell editing
this.closeCell(e.container);
}
}
Demo
Now, if you like to add a condition in that event based on what you have set in your model, you can access it within event as well:
edit: function(e) {
let currentColumn = this.options.columns[e.container.index()].field,
model = this.dataSource.options.schema.model.fields[currentColumn];
if (model.editable === false) {
// Cancels a new row
if (arguments, e.model.isNew()) {
this.cancelRow(e.container.parent());
}
else { // Cancels a cell editing
this.closeCell(e.container);
}
}
}
Demo
You can add an option yourself in the model to set if the column can be updated or only created, and handle that information inside the event, canceling the editing whenever you like.
This is how I just did it, though there are other ways.
In columns option if you remove the field option from a column it doesn't know from where to bind it.
Then use the template option to show(bind) the id. Thus making it readonly
columns: [
{
title: 'Id', width: "40px",
template: "#= id #",
},
...]

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
}
}

ExtJS display RowExpander on condition only

I currently have a rather big Grid and am successfully using the RowExpander plugin to display complementary informations on certain rows. My problem is that it's not all rows that contain the aforementioned complementary informations and I do not wish the RowExpander to be active nor to show it's "+" icon if a particular data store's entry is empty. I tried using the conventional "renderer" property on the RowExpander object, but it did not work.
So basically, how can you have the RowExpander's icon and double click shown and activated only if a certain data store's field != ""?
Thanks in advance! =)
EDIT: I found a solution
As e-zinc stated it, part of the solution (for me at least) was to provide a custom renderer that would check my conditional field. Here is my RowExpander:
this.rowExpander = new Ext.ux.grid.RowExpander({
tpl: ...
renderer: function(v, p, record) {
if (record.get('listeRetourChaqueJour') != "") {
p.cellAttr = 'rowspan="2"';
return '<div class="x-grid3-row-expander"></div>';
} else {
p.id = '';
return ' ';
}
},
expandOnEnter: false,
expandOnDblClick: false
});
Now, the trick here is that for this particular Grid, I chose not to allow the expandOnEnter and expanOnDblClick since the RowExpander will sometimes not be rendered. Also, the CSS class of the grid cell that will hold the "+" icon is 'x-grid3-td-expander'. This is caused by the fact that the CSS class is automatically set to x-grid3-td-[id-of-column]. So, by setting the id to '' only when I'm not rendering the rowExpander, I'm also removing the gray background of the un-rendered cells. So, no double click, no enter, no icon, no gray-background. It really becomes as if there is strictly no RowExpander involved for the columns where my data store field is empty (when I want no RowExpander).
That did the trick for me. For someone that wishes to preserve the ID of the cell, or that wishes to keep the double click and enter events working, there is nothing else to do other than extending the class I guess. Hope this can help other people stuck in the position I was!
As e-zinc stated it, part of the solution (for me at least) was to provide a custom renderer that would check my conditional field. Here is my RowExpander:
this.rowExpander = new Ext.ux.grid.RowExpander({
tpl: ...
renderer: function(v, p, record) {
if (record.get('listeRetourChaqueJour') != "") {
p.cellAttr = 'rowspan="2"';
return '<div class="x-grid3-row-expander"></div>';
} else {
p.id = '';
return ' ';
}
},
expandOnEnter: false,
expandOnDblClick: false
});
Now, the trick here is that for this particular Grid, I chose not to allow the expandOnEnter and expandOnDblClick specifically since the RowExpander will sometimes not be rendered. Also, the CSS class of the grid cell that will hold the "+" icon is 'x-grid3-td-expander'. This is caused by the fact that the CSS class is automatically set to x-grid3-td-[id-of-column]. So, by setting the id to an empty string only when I'm not rendering the rowExpander, I'm also removing the gray background of the cells that won't offer any expanding. So, no double click, no enter, no icon, no gray-background. It really becomes as if there is strictly no RowExpander involved for the columns where my data store field is empty (when I want no RowExpander).
That did the trick for me. For someone that wishes to preserve the ID of the cell, or that wishes to keep the double click and enter events working, there is nothing else to do other than extending the RowExpander class in my opinion. Of course, one could also use Ext.override(), but then all instances of RowExpander would be hit by the override.
I have the same task, there is my solution
var rowExpander = new Ext.ux.grid.RowExpander({
renderer : function(v, p, record){
return record.get('relatedPageCount') > 0 ? '<div class="x-grid3-row-expander"> </div>' : ' ';
}
});
I have overridden render method which test relatedPageCount field in store and render + or white space.
I think I've found a cleaner solution.Give me a feedback pls :)
I extend the toggleRow method of RowExpander and if I match a condition avoid to toggle the row.Otherwise the standard flow continues
Ext.create('customplugins.grid.plugin.ClickRowExpander',{
pluginId : 'rowexpander',
rowBodyTpl : new Ext.XTemplate(
'<p><b>Last Modified By:</b> {usermodify}</p>',
'<p><b>User data:</b> {userdata}</p>',
'<p><b>Correlation ID:</b> {correlationid}</p>',
'<p><b>Description:</b> {descr}</p>'
),
toggleRow : function(rowIdx, record) {
if(record.get('directory')) return false;
customplugins.grid.plugin.ClickRowExpander.prototype.toggleRow.apply(this, arguments);
}
})
This version works in Ext JS 5 and 6 (classic)
One thing is to remove the +/- icon, which can be done via grid viewConfig:
getRowClass: function (record, rowIndex, rowParams, store) {
var yourFieldofChoice = record.get('yourFieldofChoice');
if (yourFieldofChoice == null) {
return 'hide-row-expander';
}
},
Define css for hide-row-expander:
.hide-row-expander .x-grid-row-expander {
visibility: hidden;
}
Now you disable expanding on enter key ('expandOnEnter' config is no longer supported in Ext JS 6) or double click by overriding toggleRow, or if you do not wish the override you create your custom rowexpander built on existing plugin:
Ext.define('RowExpander', {
extend: 'Ext.grid.plugin.RowExpander',
alias: 'plugin.myExpander',
init: function (grid) {
var me = this;
me.grid = grid;
me.callParent(arguments);
},
requiredFields: ['yourFieldofChoice'],
hasRequiredFields: function (rec) {
var valid = false;
Ext.each(this.requiredFields, function (field) {
if (!Ext.isEmpty(rec.get(field))) {
valid = true;
}
});
return valid;
},
toggleRow: function (rowIdx, record) {
var me = this, rec;
rec = Ext.isNumeric(rowIdx)? me.view.getStore().getAt(rowIdx) : me.view.getRecord(rowIdx);
if (me.hasRequiredFields(rec)) {
me.callParent(arguments);
}
}
});
I have handled the beforeexpand event inside the listeners of Ext.ux.grid.RowExpander. beforeexpand method got the whole row data injected. Checking the data conditionally we can return true or false. If we return false it wont expand otherwise it will do.
var expander = new Ext.ux.grid.RowExpander({
tpl: '<div class="ux-row-expander"></div>',
listeners: {
beforeexpand : function(expander, record, body, rowIndex){
var gpdata = record.data.GROUP_VALUES[1].COLUMN_VALUE
if(gpdata == null){
return false;
}
else{
return true;
}
}
}
});

Categories