I am having trouble to bind a String value of 00 and 98 to false and true. I have found quite a few possible solutions but none of them works for me and I don't quite understand why.
Suppose I receive data from a server and create a JSON Model and set that to the table model.
function createTableColumns(columns) {
var oTable = sap.ui.getCore().byId("mainTable");
var statusTemplate = new sap.ui.commons.CheckBox({
editable: false,
// THIS WAS MY FIRST ATTEMPT TO GET IT WORKING
//checked: {
// path: "{TableModel>status}",
// formatter: function(val) {
// console.log(val);
// return val === "98";
// }
//}
});
// SECOND ATTEMPTS, DOESN'T WORK EITHER
statusTemplate.bindProperty("checked", "{TableModel>status}", function(val) { return val === "98"; });
for(var i = 0; i < columns.length; i++) {
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: columns[i]}),
name: columns[i],
flexible: false,
autoResizable: true,
template: columns[i] === 'status' ? statusTemplate : new sap.ui.commons.TextView({text: "{TableModel>" + columns[i] + "}"}),
sortProperty: columns[i],
filterProperty: columns[i],
}));
}
}
Both ways in the code above do not work. I don't know whether it is the logic or whether I am using the model wrong. Every other (TextView) Column displays data to which it is bound... so I believe that the binding is correct!?
I also have tried this way but that doesn't work at all for me: OpenUI5 binding property with a function, instead of direct access
I keep on getting the error that "00" is not a valid value for the checkbox.
Am I doing something obviously wrong?
EDIT: Current state
This function is basically called everytime the user switches
the table in the application. The old data (rows and columns) will be
deleted and filled new. The parameter columns contains an array of
strings of the column names! No data is in the data model yet!!!
function createTableColumns(columns) {
var oTable = sap.ui.getCore().byId("mainTable");
oTable.destroyColumns();
sap.ui.getCore().setModel(null, "TableModel");
var statusCheckBoxTemplate = new sap.ui.commons.CheckBox({
text: "{TableModel>status}",
editable: false,
checked: {
path: "{TableModel>status}",
formatter: function(v) {
console.debug(v);
if(v === "98") return true;
else return false;
}
}
});
for(var i = 0; i < columns.length; i++) {
if(columns[i] !== 'rowid') {
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: columns[i]}),
name: columns[i],
flexible: false,
autoResizable: true,
template: columns[i] === 'status' ? statusCheckBoxTemplate : new sap.ui.commons.TextView({text: "{TableModel>" + columns[i] + "}"}),
sortProperty: columns[i],
filterProperty: columns[i],
}));
}
}
}
After a user selected a table to display it sits there only displaying
the columns. Data is fetched from the server (ajax call) as an JSON object and a data model is created. It all works fine. Data is bound without problems and displayed correctly.
function tableBtnReloadPressed() {
// ajax call
var tabledata = readTableData(ACTIVE_TABLE);
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(tabledata);
sap.ui.getCore().setModel(oModel, "TableModel");
var oTable = sap.ui.getCore().byId("mainTable");
oTable.setModel(oModel);
oTable.bindRows("TableModel>/");
}
EDIT: Third try with factory
function createTableColumns(columns) {
var oTable = sap.ui.getCore().byId("mainTable");
oTable.destroyColumns();
sap.ui.getCore().setModel(null, "TableModel");
sap.ui.model.SimpleType.extend("BooleanStringType", {
formatValue: function(s) {
console.debug(typeof s, s);
return s === "98";
},
parseValue: function(s) {
console.debug(typeof s, s)
return s ? "98" : "00";
},
validateValue: function(s) {
console.debug(typeof s, s)
}
});
var statusCheckBoxTemplate = new sap.ui.commons.CheckBox({
text: "{TableModel>status}",
editable: false,
//checked: {
// path: "{TableModel>status}",
// formatter: function(v) {
// console.debug(v);
// if(v === "98") return true;
// else return false;
// }
//}
});
statusCheckBoxTemplate.bindProperty("checked", {
path: "{TableModel>status}",
type: new BooleanStringType()
});
for(var i = 0; i < columns.length; i++) {
if(columns[i] !== 'rowid') {
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: columns[i]}),
name: columns[i],
flexible: false,
autoResizable: true,
template: columns[i] === 'status' ? statusCheckBoxTemplate : new sap.ui.commons.TextView({text: "{TableModel>" + columns[i] + "}"}),
sortProperty: columns[i],
filterProperty: columns[i],
}));
}
}
}
You should simplify to get it working. First thing is to use a textview / label to check if the binding is working. Only then change to the checkbox and use a formatter / custom datatype for the conversion.
For instance, this is not valid (from the code above):
checked: {
path: "{TableModel>status}",
because when you pass an explicit path property, you should not use the {} in the string.
Ok, I put this into jsbin and played arount wiht it a bit. jsbin with solution
The correct template for the checkbox is this:
var statusCheckBoxTemplate = new sap.ui.commons.CheckBox({
text: "{TableModel>status}",
editable: false,
checked: {
path: "TableModel>status",
formatter: function(v) {
return(v === "98");
}
}
});
Edit: #jumpifzero beat me to it. But I wanted to edit my post for a complete picture. Such an easy to miss answer. ^^"
Related
For the combobox field, in the edit window, I need to make the field change only one value up or down, like when creating a new record or editing it.
....
{
xtype: 'combobox',
name: 'status',
fieldLabel: 'Status',
displayField: 'name',
valueField: 'id',
queryMode: 'local',
store: new Ext.data.ArrayStore({
id: 0,
fields: ['id','name'],
data: [[1, 'Новая'], [2, 'В работе'], [3, 'В ожидании'], [4, 'Закрытая'], [5, 'Архивная']]
}),
listeners: {
'select': function (combo, record) {
index = record.internalId;
filterCombo(combo, index);
},
'render': function (combo) {
//index = combo.getSelection().internalId;
//filterCombo(combo, index);
}
}
},
....
I do it using select and render events. The filterCombo function looks like this:
function filterCombo(combobox, index) {
store = combobox.getStore();
store.clearFilter();
store.filterBy(
function(record) {
if ((record.internalId == index - 1) || (record.internalId == index) || (record.internalId == index + 1)) {
return true;
} else {
return false;
}
}
);
}
When performing render, an error in combo.getSelection () (ReferenceError: index is not defined). Why?
Is it possible to implement this logic more concisely, for example in ViewController in addItem, editItem methods. Ie to filter a store at the moment of opening a form for adding / editing, or is this an option not very much?
If to stop on the 1st point, then where it would be most correct to take out the filterCombo function that would not leave it in the App.view.TestEdit view
Example Fiddle
Thank
I have a fiddle which demonstrates this strange behaviour. In a nutshell, I have a custom field which extends Ext.DataView. I need to extend dataview, because this field is supposed to have dynamic contents. This is how my field is defined:
Ext.define('Ext.ux.SimpleList', {
extend: 'Ext.DataView',
alias: 'widget.simplelist',
requires: [
'Ext.XTemplate'
],
itemSelector: 'div.record',
isFormField: true,
getFieldIdentifier: function () {
return this.name;
},
getModelData: function() {
var me = this;
var data = {};
data[me.getFieldIdentifier()] = me.getValue();
return data;
},
getSubmitData: function() { return {}; },
submitValue: true,
isValid: function () { return true; },
isDirty: function () { return true; },
validate: function () { return true; },
isFileUpload: function() { return false; },
constructor: function(config) {
Ext.applyIf(config, {
tpl: [
'{% var name = this.owner.name; %}',
'<tpl for=".">',
'<div class="record"><input record-id="{id}" type="checkbox" name="{[name]}" /> {label}</div>',
'</tpl>',
{compiled: true}
]
});
this.callParent([config]);
},
getValue: function () {
var cb = this.el.select("input").elements, i, res = [];
for (i in cb) {
if (cb.hasOwnProperty(i) && cb[i].checked) {
res.push(cb[i].getAttribute("record-id"));
}
}
return res;
},
setValue: function (values) {
//not yet implemented
}
});
And this is how I add this field to a form:
Ext.create("Ext.form.Panel",{
renderTo: Ext.getBody(),
items:[{
xtype: "textfield",
name: "text"
},{
xtype: "simplelist",
name: "list",
store: {
fields: ["id", "label", "checked"],
data: [{"id": "1", "label": "One"},{"id": "2", "label": "Two"}]
}
},{
xtype: "button",
text: "Submit",
handler: function () {
var frm = this.up("form").getForm();
console.log(frm.getFieldValues()); // it' ok
//simplelist field is not submitted
this.up("form").getForm().submit({
url: "/"
});
}
}]
});
As you can see, when I submit the form I log to the console form field values. And what is interesting about that, is that I see my custom field among those field values. So, I have a field with isFormField set to true, this field is in the list returned by form getFields() method and this field is also among those values returned by form getFieldValues() method, but still this field is not submitted. What is wrong with that and how can I fix it?
Your code uses basicForm.getFieldValues(), which calls basicForm.getValues() with some parameters, while the form while submitting uses the same method with different parameters. One of those parameters is useDataValues, which decides whether to use the getModelData or getSubmitData.
You are returning empty object in your getSubmitData method, which prevents it to correctly get the values.
All you need to change, for both methods to work in your current state, is this:
getSubmitData: function() {
return this.getModelData();
}
I'm having an issue with Kendo Grid in Angular where the custom drop down I've implemented will not open when tab navigating to that column. The built in text and number editor fields are editable on tab navigation but my custom drop down will not expand. I have to click on it to get the drop down effect.
My goal here is to allow the user to log an an entire row of data without having to take their hands off the keyboard.
My column is defined like so:
gridColumns.push({
field: currentField.FieldName.replace(/ /g, "_"),
title: currentField.FieldName,
editor: $scope.dropDownAttEditor,
template: function (dataItem) {
return $scope.dropDownTemplate(dataItem, currentField.FieldName);
}
});
My gridOptions are defined as follows:
$scope.gridOptions = {
dataSource: new kendo.data.DataSource({
transport: {
read: {
url: appconfig.basePath + '/api/DrillHoleManager/DrillHoleInterval',
type: 'POST',
contentType: 'application/json'
},
update: {
url: appconfig.basePath + '/api/DrillHoleManager/DrillHoleIntervalUpdate',
type: 'POST',
contentType: 'application/json'
},
parameterMap: function (data, operation) {
if (operation === "read") {
data.DrillHoleId = $scope.entity.Id;
data.DrillHoleIntervalTypeId = $stateParams.ddhinttypeid;
// convert the parameters to a json object
return kendo.stringify(data);
}
if (operation === 'update') {
// build DrillHoleIntervalDto object with all ATT/CMT values to send back to server
var drillHoleInterval = { Id: data.Id, Name: data.Name, From: data.From, To: data.To };
drillHoleInterval.Attributes = [];
drillHoleInterval.Comments = [];
var attributeFields = $.grep($scope.currentFields, function (e) { return e.DrillHoleTabFieldType == DrillHoleTabFieldTypeEnum.IntervalAttribute });
$.each(attributeFields, function (idx, attributeField) {
drillHoleInterval.Attributes.push({
Id: attributeField.AttributeDto.Id,
LookupId: data[attributeField.FieldName.replace(/ /g, "_")]
});
});
var commentFields = $.grep($scope.currentFields, function (e) { return e.DrillHoleTabFieldType == DrillHoleTabFieldTypeEnum.IntervalComment });
$.each(commentFields, function (idx, commentField) {
drillHoleInterval.Comments.push({
Id: commentField.CommentDto.Id,
Value: ((data[commentField.FieldName.replace(/ /g, "_")] != "") ? data[commentField.FieldName.replace(/ /g, "_")] : null)
});
});
return kendo.stringify(drillHoleInterval);
}
// ALWAYS return options
return options;
}
},
schema: { model: { id : "Id" }},
serverPaging: false,
serverSorting: false,
serverFiltering: false
//,autoSync: true
}),
columns: gridColumns,
dataBound: onDataBound,
autoBind: false,
navigatable: true,
scrollable: false,
editable: true,
selectable: true,
edit: function (e) {
var grid = $("#ddhintgrid").data("kendoGrid");
//grid.clearSelection();
grid.select().removeClass('k-state-selected');
// select the row currently being edited
$('[data-uid=' + e.model.uid + ']').addClass('k-state-selected');
e.container[0].focus();
}
};
Here is a custom event to handle the 'Tab' keypress. The point of this is I want a new record automatically added to the grid if the user presses 'Tab' at the end of the last line:
$("#ddhintgrid").keydown(function (e) {
if (e.key == "Tab") {
var grid = $("#ddhintgrid").data("kendoGrid");
var data = grid.dataSource.data();
var selectedItem = grid.dataItem(grid.select());
var selectedIndex = null
if (selectedItem != null) {
selectedIndex = grid.select()[0].sectionRowIndex;
if (selectedIndex == data.length - 1) { // if the bottom record is selected
// We need to manually add a new record here so that the new row will automatically gain focus.
// Using $scope.addRecord() here will add the new row but cause the grid to lose focus.
var newRecord = { From: grid.dataSource.data()[selectedIndex].To };
var currentCmtFields = $.grep($scope.currentFields, function (e) { return e.DrillHoleTabFieldType == DrillHoleTabFieldTypeEnum.IntervalComment; });
$.each(currentCmtFields, function (idx, currentCmtField) {
newRecord[currentCmtField.FieldName.replace(/ /g, "_")] = null;
});
grid.dataSource.insert(data.length, newRecord);
// edit the new row
grid.editRow($("#ddhintgrid tr:eq(" + (data.length) + ")"));
}
}
}
});
Here is my template for the drop down column:
$scope.dropDownTemplate = function (dataItem, fieldName) {
var currentLookups = $.grep($scope.currentFields, function (e) { return e.FieldName == fieldName; })[0].AttributeDto.Lookups;
var selectedLookup = $.grep(currentLookups, function (e) { return e.Id == dataItem[fieldName.replace(/ /g, "_")]; })[0];
// With the custom dropdown editor when going from null to a value the entire lookup object (id, name) is placed in the
// dataItem[field_name] instead of just the id. We need to replace this object with just the id value and return the name of
// the lookup to the template.
if (typeof selectedLookup == 'undefined' && dataItem[fieldName.replace(/ /g, "_")] != null) {
selectedLookup = angular.copy(dataItem[fieldName.replace(/ /g, "_")]);
dataItem[fieldName.replace(/ /g, "_")] = selectedLookup.Id;
}
if (selectedLookup != null && selectedLookup != '') {
return selectedLookup.Name;
}
else {
return '';
}
};
And finally here is the custom editor for the drop down column:
$scope.dropDownAttEditor = function (container, options) {
var editor = $('<input k-data-text-field="\'Name\'" k-data-value-field="\'Id\'" k-data-source="ddlDataSource" data-bind="value:' + options.field + '"/>')
.appendTo(container).kendoDropDownList({
dataSource: $.grep($scope.currentFields, function (e) { return e.FieldName == options.field.replace(/_/g, ' '); })[0].AttributeDto.Lookups,
dataTextField: "Name",
dataValueField: "Id"
});
};
I know this is a lot to take in but if you have any questions just let me know.
My ultimate goal is that I want the user to be able to navigate the grid using the 'Tab' key and edit every field without having to use the mouse.
im using extjs3 . my problem is im loading the store from server side using ajax . as follows
var store_dept = new Ext.data.JsonStore({
totalProperty:'totalcount',
root:'rows_dept',
autoLoad:true,
url: '<%=getResultURL.toString()%>',
fields:[
{ name:'name'},
{ name:'id'},
{ name:'address'}
]
});
var sm_dept = new Ext.grid.CheckboxSelectionModel(
{
singleSelect: false,
checkOnly: false,
listeners: {
selectionchange: function(sm_dept) {
}
}
}
);
now im getting the response so im formatting it in renderer column as
function renderBufferResult_dept(value, p, record){
return String.format('<div style="white-space:normal !important;"><b>{1}</b><br/>{3}<br/>{2}<br/></div>',value,record.data.name,record.data.address,record.data.id);
}
the grid code is :
var grid_dept= new Ext.grid.GridPanel({
id:'resgriddept',
width:210,
height:300,
title:'Additional Notification',
store: store_dept,
trackMouseOver:false,
disableSelection:true,
loadMask: true,
sm:sm_dept,
// grid columns
columns:[
sm_dept,
{
header: "Details",
dataIndex: 'id',
width:210,
sortable: true,
renderer:renderBufferResult_dept
}
] ,
buttons: [
{
text:'Export To Excel',
handler: function()
{
if(property_list!=''){
/* var prop_list='';
for(var i=0 ;i<sm.selections.getCount();i++){
prop_list =prop_list+ sm.selections.get(i).data.id+',';
} */
window.open('<%=getxlFileURL%>'+'&id_list='+property_list);
}else{
alert('Select propert to Export');
}
}
},{
text:'Generate Letter',
handler: function()
{
var dept_id_list = '0,';
if(sm_dept.selections.getCount()>0){
alert('cont select');
for(var j=0 ;j<sm_dept.selections.getCount();j++){
alert("id "+sm_dept.selections.get(j).data.id);
dept_id_list = dept_id_list+sm_dept.selections.get(j).data.id+',';
alert('id with templist '+dept_id_list);
}
}
window.open('<%=getreportsURL%>'+'&id_list='+property_list+'&dept_id_list='+dept_id_list);
}
}],
buttonAlign:'center'
});//End Of Grid
// render it
grid_dept.render('res-grid-dept');
store_dept.load();
The problem comes when i hit generate letter button, the id's of the checked rows(1,2,3) comes like 0,1,1,2 when it must come like 0,1,2,3 in the alert.
This is happening because you use get method of MixedCollection while you should use itemAt. In api you can read that this method returns the item associated with the passed key (id in your case) OR index and that key has priority over index. So when you pass 0 then this is treated as index, because you don't have such key and for that index id is 1. But when you pass 1 then it is treated as key (id in other words) so it returns item with id 1.
Replace alert("id "+sm_dept.selections.get(j).data.id); with alert("id "+sm_dept.selections.itemAt(j).data.id); and you'll be good.
I modified the following example code to checkbox model. Here is the link
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.plugin.DragDrop
Two questions, first:
When dragging an item, all the selected items are being moved too. How to drag only one item each time?
Another question:
When dragging an item, it is forced to become selected. How to make it remain state unchange? (keep unselected when it is unselected before the drag, and vice versa)
And I am using version 4.2.1.
Here is the code modified from the given example:
Ext.onReady(function () {
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name'],
data: [
["Lisa"],
["Bart"],
["Homer"],
["Marge"]
],
proxy: {
type: 'memory',
reader: 'array'
}
});
Ext.create('Ext.grid.Panel', {
store: 'simpsonsStore',
selModel: {mode: 'SIMPLE'}, //added
selType: 'checkboxmodel', //added
columns: [{
header: 'Name',
dataIndex: 'name',
flex: true
}],
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
dragText: 'Drag and drop to reorganize'
}
},
height: 200,
width: 400,
renderTo: Ext.getBody()
});
});
Thank you!
You need to overwrite the dragZone in the DragDrop plugin, so it is only sending this record.
the drag has a mousedown event, which is selecting the rows in the grid (because this has a mousedown event too), so it's fired before drag ends.
To understand this I explain this events (for more info w3schools:
row selection event: this is a mousedown event on a grid row.
row drag event: drag = mousepress + (optional) mousemove, BUT: mousepress doesn't really exist so it decides it with the help of time between mousedown and mouseup
the time measurement is done with delayedTasks
if mouseup fired before the delayed time, then it will not be executed, else drag starts
row drop event: drop = dragged + mouseup
There are more ways to prevent this:
try to put the selection to another event, which is fired after drag starts, but it can be messy because this event is used lots of times...
it's selecting it on mousedown, but we deselect it on drag start event and at drop we prevent the selection, I do this in the code.
The working code:
Ext.create('Ext.data.Store', {
storeId:'simpsonsStore',
fields:['name'],
data: [["Lisa"], ["Bart"], ["Homer"], ["Marge"]],
proxy: {
type: 'memory',
reader: 'array'
}
});
Ext.create('Ext.grid.Panel', {
store: 'simpsonsStore',
selModel: {mode: 'SIMPLE'}, //added
selType: 'checkboxmodel', //added
columns: [
{header: 'Name', dataIndex: 'name', flex: true}
],
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
dragText: 'Drag and drop to reorganize',
onViewRender : function(view) {
var me = this,
scrollEl;
if (me.enableDrag) {
if (me.containerScroll) {
scrollEl = view.getEl();
}
me.dragZone = new Ext.view.DragZone({
view: view,
ddGroup: me.dragGroup || me.ddGroup,
dragText: me.dragText,
containerScroll: me.containerScroll,
scrollEl: scrollEl,
//to remember if the row was selected originally or not
onBeforeDrag: function(data, e) {
var me = this,
view = data.view,
selectionModel = view.getSelectionModel(),
record = view.getRecord(data.item);
if (!selectionModel.isSelected(record)) {
data.rowSelected = false;
}
return true;
},
onInitDrag: function(x, y) {
var me = this,
data = me.dragData,
view = data.view,
selectionModel = view.getSelectionModel(),
record = view.getRecord(data.item);
//for deselect the dragged record
if (selectionModel.isSelected(record) && data.rowSelected == false) {
selectionModel.deselect(record, true);
}
//added the original row so it will handle that in the drag drop
data.records = [record];
me.ddel.update(me.getDragText());
me.proxy.update(me.ddel.dom);
me.onStartDrag(x, y);
return true;
}
});
}
if (me.enableDrop) {
me.dropZone = new Ext.grid.ViewDropZone({
view: view,
ddGroup: me.dropGroup || me.ddGroup,
//changed the selection at the end of this method
handleNodeDrop : function(data, record, position) {
var view = this.view,
store = view.getStore(),
index, records, i, len;
if (data.copy) {
records = data.records;
data.records = [];
for (i = 0, len = records.length; i < len; i++) {
data.records.push(records[i].copy());
}
} else {
data.view.store.remove(data.records, data.view === view);
}
if (record && position) {
index = store.indexOf(record);
if (position !== 'before') {
index++;
}
store.insert(index, data.records);
}
else {
store.add(data.records);
}
if (view != data.view) {
view.getSelectionModel().select(data.records);
}
}
});
}
}
}
},
height: 200,
width: 400,
renderTo: Ext.getBody()
});
Thanks to Alexander's reply. After reading his reply, I get into the related source code of Extjs. And finally solved the problem of changing state back immediately instead of keep it remains unchange. The code:
Ext.onReady(function () {
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name'],
data: [
["Lisa"],
["Bart"],
["Homer"],
["Marge"]
],
proxy: {
type: 'memory',
reader: 'array'
}
});
Ext.create('Ext.grid.Panel', {
store: 'simpsonsStore',
/* Start: Code block added to the original example */
selModel: {mode: 'SIMPLE', onRowMouseDown: Ext.emptyFn /* throw away onRowMouseDown handler to answer Q2 */},
selType: 'checkboxmodel',
listeners: {
afterrender: function(){
/* override the original handleNodeDrop function to answer Q1 */
this.view.plugins[0].dropZone.handleNodeDrop = function(data, record, position) {
var view = this.view,
store = view.getStore(),
index, records, i, len;
if (data.copy) {
records = data.records;
data.records = [];
for (i = 0, len = records.length; i < len; i++) {
data.records.push(records[i].copy());
}
} else {
data.view.store.remove(data.records, data.view === view);
}
if (record && position) {
index = store.indexOf(record);
if (position !== 'before') {
index++;
}
store.insert(index, data.records);
}
else {
store.add(data.records);
}
// view.getSelectionModel().select(data.records);
};
/* override the original onInitDrag function to answer Q2 */
this.view.plugins[0].dragZone.onInitDrag = function(x, y){
var me = this,
data = me.dragData,
view = data.view,
selectionModel = view.getSelectionModel(),
record = view.getRecord(data.item);
// if (!selectionModel.isSelected(record)) {
// selectionModel.select(record, true);
// }
// data.records = selectionModel.getSelection();
data.records = [selectionModel.lastFocused];
me.ddel.update(me.getDragText());
me.proxy.update(me.ddel.dom);
me.onStartDrag(x, y);
return true;
};
}
},
/* End: Code block added to the original example */
columns: [{
header: 'Name',
dataIndex: 'name',
flex: true
}],
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
dragText: 'Drag and drop to reorganize'
}
},
height: 200,
width: 400,
renderTo: Ext.getBody()
});
});
If anyone is interested in 4.1.1 Solution here is the modified Alexander's code that keeps previously selected rows selected after drop.
I slightly modified onInitDrag to select already-selected row back on drag start,
and handleNodeDrop to get it selected on drop.
Ext.create('Ext.data.Store', {
storeId:'simpsonsStore',
fields:['name'],
data: [["Lisa"], ["Bart"], ["Homer"], ["Marge"]],
proxy: {
type: 'memory',
reader: 'array'
}
});
Ext.create('Ext.grid.Panel', {
store: 'simpsonsStore',
selModel: {mode: 'SIMPLE'}, //added
selType: 'checkboxmodel', //added
columns: [
{header: 'Name', dataIndex: 'name', flex: true}
],
resizable: true,
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
dragText: 'Drag and drop to reorganize',
onViewRender : function(view) {
var me = this,
scrollEl;
if (me.enableDrag) {
if (me.containerScroll) {
scrollEl = view.getEl();
}
me.dragZone = new Ext.view.DragZone({
view: view,
ddGroup: me.dragGroup || me.ddGroup,
dragText: me.dragText,
containerScroll: me.containerScroll,
scrollEl: scrollEl,
//to remember if the row was selected originally or not
onBeforeDrag: function(data, e) {
var me = this,
view = data.view,
selectionModel = view.getSelectionModel(),
record = view.getRecord(data.item);
if (!selectionModel.isSelected(record)) {
data.rowSelected = false;
} else {
data.rowSelected = true;
}
return true;
},
onInitDrag: function(x, y) {
var me = this,
data = me.dragData,
view = data.view,
selectionModel = view.getSelectionModel(),
record = view.getRecord(data.item);
//to deselect the dragged record
if (selectionModel.isSelected(record) && data.rowSelected == false) {
selectionModel.deselect(record, true);
} else {
selectionModel.select(record, true);
}
//added the original row so it will handle that in the drag drop
data.records = [record];
me.ddel.update(me.getDragText());
me.proxy.update(me.ddel.dom);
me.onStartDrag(x, y);
return true;
}
});
}
if (me.enableDrop) {
me.dropZone = new Ext.grid.ViewDropZone({
view: view,
ddGroup: me.dropGroup || me.ddGroup,
//changed the selection at the end of this method
handleNodeDrop : function(data, record, position) {
var view = this.view,
store = view.getStore(),
selectionModel = view.getSelectionModel(),
index, records, i, len;
if (data.copy) {
records = data.records;
data.records = [];
for (i = 0, len = records.length; i < len; i++) {
data.records.push(records[i].copy());
}
} else {
data.view.store.remove(data.records, data.view === view);
}
if (record && position) {
index = store.indexOf(record);
if (position !== 'before') {
index++;
}
store.insert(index, data.records);
}
else {
store.add(data.records);
}
//select row back on drop if it was selected
if (data.rowSelected) {
selectionModel.select(data.records, true);
}
if (view != data.view) {
view.getSelectionModel().select(data.records);
}
}
});
}
}
}
},
height: 200,
width: 400,
renderTo: Ext.getBody()
});
PS: easiest way to test - https://fiddle.sencha.com/#view/editor
just select 4.1.1 and copy-paste.