Programmatically trigger onRowClicked-event - javascript

Is there a way to manually trigger the Grid-Event onRowClicked programmatically? If I set a node to selected via
node.setSelected(true);
, the event isn't being triggered... Only if I really click on it, but I need to trigger it programmatically too, as a reaction to a service-call.

Seems pretty simple to me. Just call the onRowClicked function on your gridOptions. Seeing as you already have your node, you should be able to get the row and pass it to your onRowClicked function.
var gridOptions = {
columnDefs: columnDefs,
rowData: rowData,
onRowClicked: function(params)
{
console.log('Row Make: ' + params.data.make);
}
};
function clickRowOne()
{
const node = gridOptions.api.getRowNode(0);
gridOptions.onRowClicked(node);
}
Demo.

Related

Javascript variable scope when adding function to array

I am using TinyMCE 4 and trying to build a dynamic menu. In order to do this I am building an array of menu items which includes an onclick function. The menu displays, but the onclick function does not work because when building the array, the value I need to pass to the function is out of scope - I believe.
var MenuItems = [{"Id":"1","Name":"MenuItem 1"},{"Id":"2","Name":"MenuItem 2"}];
var Menu = [];
for (var i=0;i<MenuItems.length;i++)
{
Menu.push({
text: MenuItems[i].Name,
onclick: function(){
alert(MenuItems[i].Id);
}
});
}
In the onclick declaration, MenuItems[i].Id is not in scope - I believe.
How can I pass the values to the onclick function.
I am then passing the array to the TinyMCE plugin, but I don't believe this is a problem with TinyMCE, but posting this part in case there is a better way.
tinymce.PluginManager.add('myplugin', function(editor, url) {
editor.addButton('menu', {
text: 'MyMenu',
type: 'menubutton',
icon: false,
menu: Menu
});
});
MenuItems[] won't be available when the callback for myplugin would run.
This would also mean, that once, onclick of any menuItem is called, it would try accessing MenuItems[].
To fix this, once way could be to change the implementation like:
var MenuItems = [{"Id":"1","Name":"MenuItem 1"},{"Id":"2","Name":"MenuItem 2"}];
var Menu = [];
for (var i=0;i<MenuItems.length;i++)
{
const id = MenuItems[i].Id;
Menu.push({
text: MenuItems[i].Name,
onclick: function(){
alert(id);
}
});
}

Using ag-grid with many rows and Autosave

I'm using ag-grid (javascript) to display a large amount of rows (about 3,000 or more) and allow the user to enter values and it should auto-save them as the user goes along. My current strategy is after detecting that a user makes a change to save the data for that row.
The problem I'm running into is detecting and getting the correct values after the user enters a value. The onCellKeyPress event doesn't get fired for Backaspace or Paste. However if I attach events directly to DOM fields to catch key presses, I don't know how to know what data the value is associated with. Can I use getDisplayedRowAtIndex or such to be able to reliably do this reliably? What is a good way to implement this?
EDIT: Additional detail
My current approach is to capture onCellEditingStopped and then getting the data from the event using event.data[event.column.colId]. Since I only get this event when the user moves to a different cell and not just if they finish typing I also handle the onCellKeyPress and get the data from event.event.target (since there is no event.data when handling this event). Here is where I run into a hard-to-reproduce problem that event.event.target is sometimes undefined.
I also looked at using forEachLeafNode method but it returns an error saying it isn't supported when using infinite row model. If I don't use infinite mode the load time is slow.
It looks like you can bind to the onCellKeyDown event. This is sometimes undefined because on first keydown the edit of agGrid will switch from the cell content to the cell editor. You can wrap this around to check if there is a cell value or cell textContent.
function onCellKeyDown(e) {
console.log('onCellKeyDown', e);
if(e.event.target.value) console.log(e.event.target.value)
else console.log(e.event.target.textContent)
}
See https://plnkr.co/edit/XhpVlMl7Jrr7QT4ftTAi?p=preview
As been pointed out in comments, onCellValueChanged might work, however
After a cell has been changed with default editing (i.e. not your own custom cell renderer), the cellValueChanged event is fired.
var gridOptions = {
rowData: null,
columnDefs: columnDefs,
defaultColDef: {
editable: true, // using default editor
width: 100
},
onCellEditingStarted: function(event) {
console.log('cellEditingStarted', event);
},
onCellEditingStopped: function(event) {
console.log('cellEditingStopped', event);
},
onCellValueChanged: function(event) {
console.log('cellValueChanged', event);
}
};
another option could be to craft your own editor and inject it into cells:
function MyCellEditor () {}
// gets called once before the renderer is used
MyCellEditor.prototype.init = function(params) {
this.eInput = document.createElement('input');
this.eInput.value = params.value;
console.log(params.charPress); // the string that started the edit, eg 'a' if letter a was pressed, or 'A' if shift + letter a
this.eInput.onkeypress = (e) => {console.log(e);} // check your keypress here
};
// gets called once when grid ready to insert the element
MyCellEditor.prototype.getGui = function() {
return this.eInput;
};
// focus and select can be done after the gui is attached
MyCellEditor.prototype.afterGuiAttached = function() {
this.eInput.focus();
this.eInput.select();
};
MyCellEditor.prototype.onKeyDown = (e) => console.log(e);
// returns the new value after editing
MyCellEditor.prototype.getValue = function() {
return this.eInput.value;
};
//// then, register it with your grid:
var gridOptions = {
rowData: null,
columnDefs: columnDefs,
components: {
myEditor: MyCellEditor,
},
defaultColDef: {
editable: true,
cellEditor: 'myEditor',
width: 100
},
onCellEditingStarted: function(event) {
console.log('cellEditingStarted', event);
},
onCellEditingStopped: function(event) {
console.log('cellEditingStopped', event);
}
};

attach onclick/ng-click event to element in grid databound event

I have a TypeCtrl ES6 class angular controller which uses a kendo datagrid directive and has template for grid config options , In the template for the grid, i need to call a method from the TypeCtrl class. I need to attach an onclick or ng-click event to the span within the row of the template. However teh function that needs to be triggered on click belongs to the TypeCtrl class. How can i get the context of TypeCtrl within the databound event of teh kendo grid. I see that "this" points to the kendo grid here,
Here is what i have, please let me know as to how i can access teh controller method within the databound event
//Grid options defined in Class TypeCTrl along with openSub method
class TypeCtrl{
constructor() {}
$onInit() {
this.gridOptions = {
name: 'test',
dataBound: function(e) {
//Find the span and on click , attach the typectrl controller's opensub method
let grid = this
let item = grid.tbody.find('#testClick');
let value = item.innerHTML;
item.on('click', this.openSub(value);
}
columns: [{
field: 'subscriptionName',
hidden: true,
groupHeaderTemplate: function(dataItem) {
let temp;
let sname = dataItem.value;
if (sname) {
temp = '<span id="testClick">' + sname + '</span>';
}
return temp;
}.bind(this)
}, {
field: 'name',//Todo: show icons
title: 'name'
}, {
field: 'version',
title: 'version'
}]
}
}
openSub(name) {
alert('thisis a box');
}
}
TypeCtrl.$inject = ['$scope'];
angular.module('core').controller('TypeCtrl', TypeCtrl);
export default TypeCtrl;
I see that when i click on the span tag, the context of this is lost and opensub method is not called. I ned to get to the opensub method when clicked on the row template , can i do this in the dataBound function??
or any other way s?
The common approach is to build AngularJS app with components. If you create a component that contains your grid, then you'll be able to call openSub() method from the template: ng-click="$ctrl.openSub()". In this case, this in your method will point to the TypeCtrl.

handle dojo EdgeToEdgeStoreList event

I create an EdgeToEdgeStoreList from dojox/mobile as follow:
<ul id="listCustomers"></ul>
storeCustomers = new Memory({data: data, idProperty: "label"});
var listCustomers = new EdgeToEdgeStoreList({
select: "single",
store: storeCustomers
}, "listCustomers");
listCustomers.startup();
then I want to handle the onCheckStateChanged event:
var listCustomers = dom.byId("listCustomers");
on(listCustomers, "checkStateChanged", function (listItem, newState) {
console.log(listItem, newState);
});
but this never fires.
What is the correct method?
It's ok also a way to get an array of selected items (just one in my specific case, of course).
There are two ways to do this, either use the listitems onclick, or if you want to use checkStateChanged you have to add that listener Widget.
var listCustomers = dijit.registry.byId("listCustomers");
on(listCustomers, "checkStateChanged", function (listItem, newState) {
console.log(listItem, newState);
});

ExtJs: determine grid that fires the update event on a store

i use a livegrid in ExtJs 3.3.1 but believe this question is global to ExtJs.
How does a listener on a store know which grid the event comes from ?
Here why and some code.
I have a listener on a store and on update i would like to know which rows were selected in the grid and also suspend the events. This all so that i can make a selection in the grid, update a field in that range and update that field in the whole selection. Selection is done without a checkbox, just by highlighting the rows. Since this listener is used by many grids i need a way to get it froml what the gridlistener gets as parameters but that is only store, record and action
Ext.override(Ext.ux.grid.livegrid.Store, {
listeners: {
'update': function(store, record, action) {
if (action=='commit'){ //each update has 2 actions, an edit and a commit
var selected = grid.getSelectionModel().getSelections(); //need to know which grid
if (selected.length>1){ //if more than one row selected
grid.suspendEvents();
store.writer.autoSave = false;
for(var i=0; i < selected.length; i++){
if (this.fieldChanged) {
for (var name in this.fieldChanged) {
//get the field changed and update the selection with the value
if (selected[i].get(name)!=this.fieldChanged[name]){
selected[i].set(name, this.fieldChanged[name]);
}
}
}
}
grid.resumeEvents();
store.fireEvent("datachanged", store);
store.writer.autoSave = true;
}
}
if (action=='edit'){
this.fieldChanged = record.getChanges()
}
}
}
});
It would be easier in an extension but it can be done in an override as well.
MyGridPanel = Ext.extend(Ext.ux.grid.livegrid.EditorGridPanel, {
initComponent: function(){
MyGridPanel.superclass.initComponent.call(this);
this.store.grid = this;
}
});
edit --- Showing how to do it in an override, it isn't pretty but it is useful.
var oldInit = Ext.ux.grid.livegrid.EditorGridPanel.prototype.initComponent;
Ext.override(Ext.ux.grid.livegrid.EditorGridPanel, {
initComponent: function(){
oldInit.call(this);
this.store.grid = this;
}
});
There may be more grids using the store. Preferably in Ext Js 4 you observe the Gridpanel class like so:
//Associate all rendered grids to the store, so that we know which grids use a store.
Ext.util.Observable.observe(Ext.grid.Panel);
Ext.grid.Panel.on('render', function(grid){
if (!grid.store.associatedGrids){
grid.store.associatedGrids=[];
}
grid.store.associatedGrids.push(grid);
});
Found a solution myself, i override the livegrid to include a reference to itself in its store like so
Ext.override(Ext.ux.grid.livegrid.EditorGridPanel, {
listeners: {
'afterrender': function(self) {
this.store.grid = this.id;
}
}
});
Then in my store listener i can refer to store.grid

Categories