How to set Max Length on ag-grid cells - max

Is there any way to impose a maxLength text allowed in an ag-grid cell, similar to the one on a normal input element?
<input maxlength="220"/>
No relative documentation was found. Also, no particular situations & more details are needed, in my opinion. Thank you!

agGrid's documentation really isn't clear on this, but it is possible.
agGrid MaxLength
In your column definitions, just add something like this:
this.columnDefs = [
{
field: 'Surname',
minWidth: 100,
editable: true,
cellEditor: 'agLargeTextCellEditor',
cellEditorParams: { maxLength: 200 }
}

Yes, you can control the full flow of input data, but you have to create your own cellEditor for that.
So - it shouldn't be hard to make a simple input validation.
and to achieve your requirements you have to take care of one function within the component:
// Gets called once when editing is finished (eg if enter is pressed).
// If you return true, then the result of the edit will be ignored.
isCancelAfterEnd?(): boolean;
isCancelAfterEnd() {
return !this.isValid(this.eInput.value);
}
isValid(value) {
return value.length <= this.maxLength;
}
Demo

Related

Get current sort options when sort changes in vuetify data tables

Our tables pagination and sorting are all done on the server, but I still want to allow the user to click column headers to sort. I need to access the tables sort options when the sorting changes. It seems the events are split
update:sort-by
update:sort-desc
I could create two methods, have the first event set the column (sort-by) value, and then the second method actually trigger the sort. But that sounds horrible and prone to race conditions or future bugs.
It would be better if the sort-by included the desc/asc data as well. I tried creating a ref to the table, but for some reason the properties containing the sort information are empty.
The event update:options contains all the necessary information, but that could fire for reasons other than sorting which isn't ideal either.
So I'm not sure if I'm missing something here. Is there a better way to accomplish this?
<v-data-table
ref="contractItemTable"
:headers="headers"
:items="contracts"
:disable-sort="isLoadingPage"
:server-items-length="tableTotal"
disable-pagination
hide-default-footer
#click:row="navigateToContract"
single-select
#update:sort-by="sortTable"
#update:sort-desc="sortTable"
item-key="id.id">
And the JS
public sortTable(event) {
console.debug(this.$refs.contractItemTable.sortBy);
console.debug(this.$refs.contractItemTable.sortDesc);
}
No matter what I click, the sortBy and sortDesc properties are empty. If I use the options event, the event contains the correct sortBy and sortDesc. But as stated above, not exactly the event I want to use. I have it working, but I have to "ignore" the initial load options event since it's not a valid time for this method to fire.
In data table add attribute:
:sort-desc.sync="sort_desc"
In data:
sort_desc:true,//or what you need by default
In observable:
sort_desc:function(val,_prev){
//do what you need to change sort and refresh
},
You're mostly there (and found your question while trying to sort out the best way to apply sorting to derived/computed column-items myself) ... just need to bind the v-data-table sort-by and sort-desc attributes to data elements so that you can refer to them in your sortTable function:
<v-data-table
...
:items="contracts"
:headers="headers"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
#update:sort-by="sortTable"
#update:sort-desc="sortTable"
...
>
export default {
data() {
contracts: [],
sortBy: 'contractDate', // make sure this matches headers[].value
sortDesc: false, // and both match your initial from-server sort
...
headers: [
{ text: 'Contract Date', sortable: true, value: 'contractDate' },
{ text: 'Contract Value', sortable: true, value: 'contractValue' }
...
]
},
methods: {
sortTable() {
if(this.sortBy === 'contractDate') {
this.contracts.sort( (a,b) => {
return ( a.contractDate > b.contractDate ? 1 : -1 ) * (this.sortDesc ? -1 : 1 );
});
}
if(this.sortBy === 'contractValue') {
this.contracts.sort( (a,b) => {
return ( a.contractValue > b.contractValue ? 1 : -1 ) * (this.sortDesc ? -1 : 1 );
});
}
}
}
}
Your sort logic obviously will vary, but included the Array.sort() callback example there to show where this.sortDesc is used to reverse the evaluation.
A big caveat to be aware of is that if you do not specify
<v-data-table :must-sort="true" >
Then the bound #update:sort-by and #update:sort-desc events will BOTH fire when sort is deactivated which happens when user clicks the same column header a third time (it cycles through sorted to no-sort states.)
To get around this, add something like
sortPending: false
to your data state, and when the event fires, return immediately out of the event if this.sortPending === true, and move your sort logic into a Vue.nextTick() callback:
methods: {
sortTable() {
if(this.sortPending) return;
this.sortPending = true;
this.$nextTick( () => {
this.sortPending = false;
/* your sort logic here */
});

HandsOnTable Dropdown Without Editable Text?

Is it possible to use a dropdown column in a HandsOnTable without the editable textbox?
I know you can set the type to dropdown and it will validate/highlight red when you enter an invalid value, but is there a way to completely disable text entry for dropdown columns? It seems just using the readOnly property on the column blocks the dropdown altogether.
As you said, the readOnly option will disable you dropdown. So I believe the closest solution you can use is the allowIndvalid = false (true by default) :
allowInvalid: true (optional) - allows manual input of value that does not exist in the source. In this case, the field background highlight becomes red and the selection advances to the next cell
allowInvalid: false - does not allow manual input of value that does not exist in the source. In this case, the ENTER key is ignored and the editor field remains opened.
Documentation Link
You can use this JSFiddle to quickly check this option
I have the same issue and was able to resolve it with such steps. Maybe this could help:
1 when creating columns add a special className to the necessary column type:
{
data: 'priceUnitsName',
type: 'dropdown',
invalidCellClassName: 'colored',
source: Object.keys(unitNames),
width: 100,
className: 'disable-edit',
}
2 Subscribe to events to handle cancel editing:
private targetCell: HTMLTableCellElement;
public settings: GridSettings = {
// your settings
afterOnCellMouseDown: (event: MouseEvent, coords: CellCoords, TD: HTMLTableCellElement) => {
this.targetCell = TD;
},
afterBeginEditing: (row: number, column: number) => {
if (this.targetCell.classList.contains('disable-edit')) { // this handle only necessary columns with special class
setTimeout(() => {
const inputCollection: HTMLCollection = document.getElementsByClassName('handsontableInput');
Array.from(inputCollection).forEach((input: HTMLTextAreaElement) => {
input.blur(); // this calls blur on element manually
});
});
}
},
Maybe this is not the best decision, but by default, handsontable can't make dropdown elements readonly with leaving open-close dropdown functional and I can't find any workable suggestion with this.
Checked on 'dropdown' and 'date' types, and it works.

YUI datatable conditional dropdown editor

I'm currently editing an application which uses YUI 2.5. I haven't used it before and could use some help.
I want to be able to add a dropdown editor for a particular column's rows using datatable, but I only want it to appear if specific values appear in another column in the corresponding row.
Is it possible to add some kind of If statement in the column definitions? Would I have to use a custom formatter?
eg.
var eventColumnDefs = [
{key:"event_id", sortable:false},
{key:"event_name", sortable:true},
{key:"extended", sortable:true, formatter: function (o) {
if (event_name=type1||event_name=type4||event_name=type5) {
editor:"dropdown", editorOptions:{dropdownOptions:eventData.extendedList}
}
}
}];
I know this code wouldn't work, by the way, I would just appreciate a bit of guidance.
You are close. In the column definition you add the information about the dropdown editor as if you always wanted it to show up. Now, going to the code sample here: http://developer.yahoo.com/yui/datatable/#cellediting
See the last line that attaches onEventShowCellEditor to whatever event you want to make the editor pop up? That is where you put the conditional. Instead of just asking to show the cell editor under any circumstance, you put some code there, like:
myDataTable.subscribe("cellClickEvent", function (ev) {
if ( ** whatever ** ) {
this.myDataTable.onEventShowCellEditor.apply(this, arguments);
}
});
I haven't been doing YUI2 for quite some time now so I don't remember the details on the arguments received by the event listener. I believe that you might also use showCellEditor() instead of onEventShowCellEditor, the later only massages the arguments as received from the event listener and ends up calling showCellEditor so you might as well skip it.
Found a hacky solution as follows
In Column Definitions:
var eventColumnDefs = [
{key:"player_name", sortable:true, editor:"dropdown", editorOptions:{dropdownOptions:currenteam}}
];
Then later on in initialiseTables:
eventDataTable.subscribe("cellClickEvent", function(ev) {
var target, column, field;
target = ev.target;
column = this.getColumn(target);
if (column.key === "player_name") {
field= this.getRecord(target).getData("team_id");
}
if (hometeamlistID == field) {
currenteam=hometeamlist;
} else if (awayteamlistID == field) {
currenteam=awayteamlist;
}
eventDataTable._oColumnSet._aDefinitions[8].editorOptions.dropdownOptions = currenteam;
});
hometeamlist, awayteamlist, hometeamlistID and awayteamlistID are pulled from an XML string. I haven't included that code above, but some of it is included in my question here:
YUI 2.5. Populating a dropdown from XML

jqGrid Custom Formatter Set Cell wont work with options.rowId

Ive been through all the posts, finally got setCell to work with hardcoded values, but not using the options.rowId.
function StatusFormatter(cellvalue, options, rowObject) {
if (cellvalue == 'C'){
jQuery("#list").setCell(options.rowId , 'SOORDLINE', '', { color: 'red' });
jQuery("#list").setCell("[2.000]", 'SOORDLINE', '', { color: 'red' });
jQuery("#list").setCell('[2.000]', 'SOREQDATE', '', { color: 'red' });
jQuery("#list").setCell(options.rowId, 'SOPRICE', '', { color: 'red' });
}
return cellvalue;
};
The FIRST and LAST lines dont work, but the 2 with the hardcoded rowId DO work. I inspected what comes back in the option.rowId and they are the same as the hardcoded values, (just different depending on the row of course. What am I missing? Please help. I dont see any difference between the lines, or values.
EDITED-
I tried the answer, and it seems to be what I need. I tried the following
{ name: 'SOORDLINE', index: 'SOORDLINE', width: 25, search: false ,celattr: function () { return ' style="color: red"'; }
},
To aleast make them all red before I dove into the logic, and it didnt do anything for me.
Sorry, but you use custom formatter in absolute wrong way. The goal of the custom formatter to to provide HTML fragment to fill the content of the cells in the corresponding column. So the StatusFormatter will be called before the row with the id equal to options.rowId will be created. Moreover for performance purpose one use typically gridview: true. in the case the whole content of the grid (the whole body of the grid) will be constructed first as string and only after that will be placed in the grid body in one operation. It improve the performance because after placing of any element web browser have to recalculate position of all other elements on the page.
If you want to set text color on the SOORDLINE cell you should cellattr instead:
celattr: function () { return ' style="color: red"'; }
The celattr can be used also in the form celattr: function (rowId, cellValue, rawObject) {...} and you can test the property of rawObject which represent of the values for any column and return the cell style based on the cell value.
Alternatively you can enumerate the rows inside of loadComplete and set the style on <tr> element instead of setting the same styles for every row. See the answer as an example.

How to customize Ext JS tree nodes properly?

Ext JS 4. I have a tree.Panel where I want to display custom HTML in each node, generated from that node’s model data. I can do this by setting the node’s text when loading the store, but it is not the model’s job to do markup. So I created a custom Column that renders my HTML.
My problem is: unless I derive from Ext.tree.Column, it doesn’t show up properly (no outline, plus/minus icons etc.). If I do, everything is fine, but Ext.tree.Column is marked as private to Ext JS.
Is there some officially supported API to do what I want?
I have written a blog post about how to customize ExtJS 4 tree panel, I hope it will help:
http://hardtouse.com/blog/?p=24
The idea is to use renderer combined with A LOT OF css magic:
columns : [{
xtype : 'treecolumn',
dataIndex : 'name',
renderer : function(value, record){
return Ext.String.format('<div class="tree-font">{0}</div>', value);
}]
Thanks for your answer above. Here is another example showing a few more options for formatting:
columns: [{
xtype: 'treecolumn',
dataIndex: 'text',
flex: 1,
renderer: function (value, metaData, record, rowIndex, colIndex, store, view) {
// see http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.tree.Column-cfg-renderer
var tooltipString = "Hello";
metaData.tdAttr = 'data-qtip="' + tooltipString + '"';
return Ext.String.format('{0} <span style="color:red;">{1}</span>', value, record.data.personname);
}
}]
You might also want to add
hideHeaders : true,
to your tree panel config to remove the "grid" header that appears as a result of using a treecolumn.
Murray

Resources