Ext js grid remove selection model - javascript

I have a situation where I need to dynamically add or remove grids selection model.
Searching the documentation I see that the selection model doesn't have a destroy() method or anything similar. How can I remove or destroy a selection model from a grid in ext js 4.x.?
If this is not possible I still have an option to revert some functionallity and dynamically add the selection model to an already created grid. But I'm also not sure if this is possible.

I'd suggest to disable the selection model instead of destroying it.
You can clear the current selection (deselectAll) and lock the selection model to prevent further selection (setLocked):
selModel.deselectAll();
selModel.setLocked(true);
As you're using a checkbox selection model, you'll also need to hide the corresponding column which is added to the grid:
grid.headerCt.child('gridcolumn[isCheckerHd]').hide();

Selection models are not designed to be replaced, so... it's gonna be complicated!
You'd have to reproduce the initialization of the sel model, unwire the previous one, and rewire the new one...
Here's an example that works in substituting a row selection model for a checkbox model. It may still contains memory leaks from listeners registered by the first selection model that I would have forgot. The creation of the new selection model relies on the getSelectionModel method of the grid, which implements the disableSelection, simpleSelect, and multiSelect options of the grid (see the code).
Ext.widget('grid', {
renderTo: Ext.getBody()
,store: ['Foo', 'Bar', 'Baz']
,selType: 'checkboxmodel'
,columns: [{
dataIndex: 'field1'
,text: "Name"
}]
,listeners: {
selectionchange: function(sm, records) {
var grid = sm.view.up(),
item = grid.down('tbtext');
if (records.length) {
item.setText(
'Selection: ' + Ext.pluck(Ext.pluck(records, 'data'), 'field1').join(', ')
);
} else {
item.setText('No selection');
}
}
}
,tbar: [{
text: "Replace selection model"
,handler: function(button) {
var grid = button.up('grid'),
headerCt = grid.headerCt,
checkColumn = headerCt.down('[isCheckerHd]'),
view = grid.view,
previous = grid.selModel,
sm;
// try to clean up
previous.deselectAll();
previous.destroy();
// sel model doesn't clear the listeners it has installed in its
// destroy method... you'll have to chase the listeners that are
// installed by the specific type of sel model you're using
if (previous.onRowMouseDown) {
view.un('itemmousedown', previous.onRowMouseDown, previous);
}
if (previous.onRowClick) {
view.un('itemclick', previous.onRowClick, previous);
}
// clear references
delete grid.selModel;
delete view.selModel;
// create another selModel
grid.selType = 'rowmodel';
//grid.disableSelection = true;
sm = grid.getSelectionModel();
// assign new sel model
view.selModel = sm;
sm.view = view;
// remove checkbox model column
if (checkColumn) {
headerCt.remove(checkColumn);
}
// init sel model is trigerred in view render events, so we must do it
// now if the view is already rendered
if (view.rendered) {
sm.beforeViewRender(view);
sm.bindComponent(view);
}
// finally, refresh the view
view.refresh();
}
}]
// a place to display selection
,bbar: [{
xtype: 'tbtext'
,text: 'No selection'
}]
});

Related

Get access to gridOptions of grid created by cell renderer

I am using ag-Grid to create a grid within a grid using a cell renderer. This is the code for the cell renderer.
// cell renderer class
function TestCellRenderer() {
}
// init method gets the details of the cell to be rendered
TestCellRenderer.prototype.init = function(params) {
this.eGui = document.createElement('div');
// console.log('params.value:', params.value);
// console.log('eGui', this.eGui.style);
this.eGui.style.width = '70%';
this.eGui.classList.add("ag-theme-balham");
this.gridOptions = {
columnDefs: params.columns,
rowData: rowDataContained,
domLayout: "autoHeight",
rowHeight: 50,
// suppressRowClickSelection: true,
popupParent: document.querySelector('body'),
rowDragManaged: true,
components: {
'actionCellRenderer': ActionCellRenderer,
'selectCellRenderer': SelectCellRenderer
},
onCellEditingStopped: function(event) {
console.log('cellEditingStopped');
},
onRowClicked: function(event) { console.log('A row was clicked:', event); },
}
// console.log('gridOptions:', this.gridOptions);
new agGrid.Grid(this.eGui, this.gridOptions);
};
TestCellRenderer.prototype.getGui = function() {
return this.eGui;
};
This screenshot will better explain what I've done.
My problem is, I have created a select2 cell editor for the "Dropdown" column but am having issues calling the api.StopEditing() function when the user clicks on an option in the select menu because it requires the gridOptions that were created on the fly using the renderer.
If the user changes focus to a different cell, the editing does stop but I want to be able to have it stop the moment the user selects a value. I was able to print something to the console when the user selects something, but I don't know how to access the gridOptions of that specific grid.
For anyone wondering, I solved the problem by adding the following to my selectCellEditor.prototype.init function:
$(this.eInput).on('select2:select', function(e) {
console.log('Works!', this);
params.stopEditing();
});
What's happening there is, the moment the user selects an option, the menu is closed and the value is changed in the cell.

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 #",
},
...]

Component lost during rerender, how to reattach?

I am rendering a component into a grid rowExpander plugin rowBodyTpl:
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : [
'<div id="contact-row-{Id}"> </div>'
]
}],
var row = 'contact-row-' + record.get('Id'),
grid = Ext.getCmp(gridId),
if(!grid) me.createSubGrid(record,gridId).render(row);
This works fine. But when the grid receives an update event for a record with certain modifiedFields, that record's rowExpander is rerendered using the rowTpl only, and the inner grid is dangling somewhere. I can access the grid using Ext.getCmp, and grid.rendered is true, but it is not shown. So I guess I have to reattach the grid after the row has been rerendered.
I think I can attach to the update event, and find out whether the rowTpl has been rerendered without the child grid using
if(!grid.container.contains(grid.el))
But is there a way to put the grid back into the dom?
I have tried
grid.container.insertFirst(grid.el);
but this does not work. The element is inserted but the grid is not displayed.
Any ideas?
The way you are doing leads to memory leaks (because your component is not destroy when the grid is re-render).
I suggest to check at : Component Template (http://skirtlesden.com/ux/ctemplate) or if you try to render a nested grid, there was several attempt to build something correct and I think a working one is the following : http://blogs.walkingtree.in/2015/06/30/nested-grid-in-sencha-ext-js/
With my trials, I already was on the right track, and the error was somewhere else entirely. The problem was that my update event fn which did the reattach was executed before the update event fn that broke everything, because the fn was fired on the same event and had the same priority, but was attached to the store earlier. Changing the priority was one option, but I just put the creation into the boxready event, which is executed after the view has attached its events to the store:
xtype:'grid',
listeners:{
boxready:function(grid) {
var store = grid.getStore();
...
store.on({
update:function(store, record) {
me.restoreSubgridDom(record);
},
beforeload:function(store) {
var records = store.getRange();
Ext.each(records,me.destroySubgrid);
}
});
}
}
with the two functions:
restoreSubgridDom: function(record) {
var row = 'contact-row-' + record.get('Id'),
gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid && !grid.container.contains(grid.el))
{
grid.container.insertFirst(grid.el);
}
},
destroySubgrid: function(record) {
var gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid) grid.destroy();
}

Dynamic default value for Kendo Grid

I want an auto increment column in my Kendo Grid. This field isn't server side auto increment, because I want the user to see the value and be able to change it.
My current solution is to add a click attribute to Create button and loop over rows to find the highest value and increment it.
But how can I insert this value inside the newly created row? Click event happens before the new row is created.
So there is two possible solution:
Have a variable as default value and update it in my JS code.
Access the newly created row somehow, and update the value.
This is my JS code:
function createClick(id) {
var grid = $("#" + id).data('kendoGrid');
var highestRadif = 0;
grid.tbody.find('>tr').each(function () {
var dataItem = grid.dataItem(this);
var radif = dataItem.SRadifReqR;
highestRadif = highestRadif < radif ? radif : highestRadif;
})
alert(++highestRadif);
}
You can use Grid's edit event to add your new generatedId value to new Grid's model.
This is some explanation from their documentation:
Edit
fired when the user edits or creates a data item.
e.container jQuery, jQuery object of the edit container element, which wraps the editing UI.
e.model kendo.data.Model, The data item which is going to be edited. Use its isNew method to check if the data item is new
(created) or not (edited).
e.sender kendo.ui.Grid, The widget instance which fired the event.
I suppose your click have something like this
//generate id code
vm.newId = ++highestRadif; // we need to store generated Id
grid.addRow();
then on edit event
edit: function(e) {
var model = e.model; // access edited/newly added model
// model is observable object, use set method to trigger change event
model.set("id", vm.newId);
}
Note: Your schema model's field must set property editable: true, due to enable us to change model field value using set method. Also if your field schema have validation required, you need to remove it.
model: {
id: "ProductID",
fields: {
ProductID: { editable: true, nullable: true },
}
}
Sample
I was able to put a function in the datasource schema for this.
schema: {
model: {
id: "id",
fields: {
currencyType: { defaultValue: getDefaultCurrency },
invoiceDate: { type: "date" }
}
}
}
function getDefaultCurrency() {
return _.find(vm.currencyTypes, { id: vm.currencyId });
};

Problem with ExtJs editor grid panel

I've an extjs editor grid panel(3.3.1) that is binded to a store. New records are added to the grid by an empty row at the top. On the load of the store I'm adding an empty row at the top of the grids. When the user adds a new value and the focus loses out I'm adding another empty row.
AV.ClassifiedCategories = Ext.extend(Ext.grid.EditorGridPanel, {
....
initComponent: function(){
this.store = this.initialConfig.store;
//add an empty row at top
this.store.on('load', this.addCategory, this);
Ext.apply(this,
{
clicksToEdit: 1,
listeners:
{
afteredit : function(e){
this.addCategory();
},
scope: this
}
});
},
//adds an empty row and insert a record to store
addCategory: function(){
var Category = this.getStore().recordType;
var cat = new Category({ cat_id: null, cat_name: "" });
this.stopEditing();
this.store.insert(0, cat);
this.startEditing(0, 0);
return cat;
},
...
});
The problem is facing here is once the afteredit event is fired and an empty row is added the focus is not moving to the first row i.e. the second row is still in edit mode. How I can solve that?
I've taken your code and have created this demo. As you can see everything works as expected. Are you sure you have provided us with non-working code?

Categories