Data is not shown in angular grid after loading from server - javascript

I'm using angular 1.4 with requirejs. I need to display the data (loaded from server) in angular grid but I'm having problem in displaying in grid at startup. Data is loaded successfully and not visible in the grid, while when I click on any of it header column, the data is suddenly visible and then it works fine.
Here is the code for loading/displaying the data.
Angular code:
var paginationOptions = {
pageNumber: 1,
pageSize: 25,
sort: null
};
$scope.gridOptions = {
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
useExternalPagination: true,
useExternalSorting: false,
columnDefs: [
{name: 'expireDate'},
{name: 'lastUpdateDate'},
{name: 'name'},
{name: 'type'},
],
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) {
if (sortColumns.length === 0) {
paginationOptions.sort = null;
} else {
paginationOptions.sort = sortColumns[0].sort.direction;
}
getPage();
});
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
getPage();
});
}
};
var getPage = function () {
require(['path/to/jsFile'], function(obj){
obj.getFHVUsersData($scope.gridOptions , paginationOptions);
});
};
getPage();
its working fine and the event getFHVUsersData() is being triggered correctly for requesting data from the server.
Here is code where I'm getting the response from server:
if (ajax.status === 200 && ajax.readyState === 4) {
var resp = JSON.parse(ajax.responseText);
fhvgridOptions.totalItems = resp.data.length;
var firstRow = (paginationOptions.pageNumber - 1) * paginationOptions.pageSize;
fhvgridOptions.data = resp.data.slice(firstRow, firstRow + paginationOptions.pageSize);
}
paginationOptions and fhvgridOptions are the global variables for arguments in the getFHVUsersData($scope.gridOptions , paginationOptions) respectively.

Related

Angularjs - NgTable got undefined in reload

i'm using Angularjs NgTable, with pagination inside of a tab provided by Angularjs Material. this works fine. i've used it in many parts of my project and realoaded it many times in differents parts.
but in this case, i can't reload the tables. and don't know what is the problem or how shoud do the reload.
i have in DistribucionController this functions:
$scope.listaFacturaTierra = function () {
var idFactura = $stateParams.idFactura;
$facturaTierra = distribucionService.getStockTierra(idFactura);
$facturaTierra.then(function (datos) {
$scope.facturaTierra = datos.data;
var data = datos;
$scope.tableFacturaTierra = new NgTableParams({
page: 1,
count: 8
}, {
total: data.length,
getData: function (params) {
data = $scope.facturaTierra;
params.total(data.length);
if (params.total() <= ((params.page() - 1) * params.count())) {
params.page(1);
}
return data.slice((params.page() - 1) * params.count(), params.page() * params.count());
}});
});
};
$scope.listaFacturaBebelandia = function () {
var idFactura = $stateParams.idFactura;
$facturaBebelandia = distribucionService.getStockBebelandia(idFactura);
$facturaBebelandia.then(function (datos) {
var data = datos.data;
$scope.facturaBebelandia = datos.data;
$scope.tableFacturaBebelandia = new NgTableParams({
page: 1,
count: 10
}, {
total: data.length,
getData: function (params) {
data = $scope.facturaBebelandia;
params.total(data.length);
if (params.total() <= ((params.page() - 1) * params.count())) {
params.page(1);
}
return data.slice((params.page() - 1) * params.count(), params.page() * params.count());
}});
});
};
$scope.listaFacturaLibertador = function () {
var idFactura = $stateParams.idFactura;
$facturaLibertador = distribucionService.getStockLibertador(idFactura);
$facturaLibertador.then(function (datos) {
var data = datos.data;
$scope.facturaLibertador = datos.data;
$scope.tableFacturaLibertador = new NgTableParams({
page: 1,
count: 10
}, {
total: data.length,
getData: function (params) {
data = $scope.facturaLibertador;
params.total(data.length);
if (params.total() <= ((params.page() - 1) * params.count())) {
params.page(1);
}
return data.slice((params.page() - 1) * params.count(), params.page() * params.count());
}});
});
};
they are displayed fine, and the pagination is working as well.
i add elements using Angularjs Material ngDialog using 3 functions the make the process.
Show the principal modal:
$scope.distribuirModal = function (producto) {
$rootScope.modalProducto = producto;
ngDialog.open({
template: 'views/modals/distribucion/modal-distribuir.html',
className: 'ngdialog-theme-advertencia',
showClose: false,
controller: 'DistribucionController',
closeByDocument: false,
closeByEscape: false
});
};
make the processs of the data, and show a modal of confirmation:
$scope.confirmarDistribuir = function (modalDistribuir) {
var control = 0;
control = modalDistribuir.tierra + modalDistribuir.bebelandia + modalDistribuir.libertador;
if (control === $rootScope.modalProducto.cantidadTotal) {
if (modalDistribuir.tierra !== null) {
$scope.wrapper.stockTierra.idProducto = $rootScope.modalProducto;
$scope.wrapper.stockTierra.cantidad = modalDistribuir.tierra;
}
if (modalDistribuir.bebelandia !== null) {
$scope.wrapper.stockBebelandia.idProducto = $rootScope.modalProducto;
$scope.wrapper.stockBebelandia.cantidad = modalDistribuir.bebelandia;
}
if (modalDistribuir.libertador !== null) {
$scope.wrapper.stockLibertador.idProducto = $rootScope.modalProducto;
$scope.wrapper.stockLibertador.cantidad = modalDistribuir.libertador;
}
ngDialog.open({
template: 'views/modals/distribucion/confirmacion-distribuir.html',
className: 'ngdialog-theme-advertencia',
showClose: false,
controller: 'DistribucionController',
closeByDocument: false,
closeByEscape: false,
data: {
'wrapper': $scope.wrapper,
'producto': $rootScope.modalProducto
}
});
} else {
$scope.alerts.push({
type: 'danger',
msg: 'La cantidad total de productos a distribuir debe ser igual a la cantidad total de productos en almacen.'
});
}
};
in this modal i execute a function that save the data on my API
$scope.finalizarDistribucion = function () {
$scope.sendWrapper = {
stockTierra: null,
stockBebelandia: null,
stockLibertador: null
};
if ($scope.ngDialogData.wrapper.stockTierra.idProducto !== null && $scope.ngDialogData.wrapper.stockTierra.cantidad) {
$scope.sendWrapper.stockTierra = $scope.ngDialogData.wrapper.stockTierra;
}
if ($scope.ngDialogData.wrapper.stockBebelandia.idProducto !== null && $scope.ngDialogData.wrapper.stockBebelandia.cantidad) {
$scope.sendWrapper.stockBebelandia = $scope.ngDialogData.wrapper.stockBebelandia;
}
if ($scope.ngDialogData.wrapper.stockLibertador.idProducto !== null && $scope.ngDialogData.wrapper.stockLibertador.cantidad) {
$scope.sendWrapper.stockLibertador = $scope.ngDialogData.wrapper.stockLibertador;
}
$distribute = distribucionService.add($scope.sendWrapper);
$distribute.then(function (datos) {
if (datos.status === 200) {
ngDialog.closeAll();
toaster.pop({
type: 'success',
title: 'Exito',
body: 'Se ha distribuido con exito los productos.',
showCloseButton: false
});
}
});
$scope.$emit('updateTables', $scope.ngDialogData.producto);
$scope.$emit('updateStock', {});
};
in this function i do two $emit
the first one update my object Producto in my ProductoController and send a $broadcast to update my principal table
$scope.$on('updateTables', function (event, object) {
var idFactura = parseInt($stateParams.idFactura);
object.estadoDistribucion = true;
$updateProducto = _productoService.update(object);
$updateProducto.then(function (datos) {
if (datos.status === 200) {
$rootScope.$broadcast('updateTableProducto', {'idFactura': idFactura});
}
});
});
this last works fine, reload the table without problems.
the second $emit is the problem, it must reload the another 3 tables
$scope.$on('updateStock', function () {
var idFactura = parseInt($stateParams.idFactura);
$facturaTierra = distribucionService.getStockTierra(idFactura);
$facturaTierra.then(function (datos) {
$scope.facturaTierra = datos.data;
$scope.tableFacturaTierra.reload();
});
$facturaBebelandia = distribucionService.getStockBebelandia(idFactura);
$facturaBebelandia.then(function (datos) {
$scope.facturaBebelandia = datos.data;
$scope.tableFacturaBebelandia.reload();
});
$facturaLibertador = distribucionService.getStockLibertador(idFactura);
$facturaLibertador.then(function (datos) {
$scope.facturaLibertador = datos.data;
$scope.tableFacturaLibertador.reload();
});
});
but my parameters of ngTable are undefined and the reload fails.
have somebody any idea what i'm doing wrong?
Finally after try many times i got the answer.
First in my ProductoController i did a $broadcast to my DistribucionController
$rootScope.$on('updateTableProducto', function (event, object) {
$list = _productoService.searchByIdFactura(object.idFactura);
$list.then(function (datos) {
$scope.productosFactura = datos.data;
$rootScope.$broadcast('updateStock', {});
$scope.tableProductosFactura.reload();
});
});
then on i receive this $broadcast on my another controller using
$scope.$on('updateStock', function (event, object) {
var idFactura = parseInt($stateParams.idFactura);
$facturaTierra = distribucionService.getStockTierra(idFactura);
$facturaTierra.then(function (datos) {
$scope.facturaTierra = datos.data;
$scope.tableFacturaTierra.reload();
});
$facturaBebelandia = distribucionService.getStockBebelandia(idFactura);
$facturaBebelandia.then(function (datos) {
$scope.facturaBebelandia = datos.data;
$scope.tableFacturaBebelandia.reload();
});
$facturaLibertador = distribucionService.getStockLibertador(idFactura);
$facturaLibertador.then(function (datos) {
$scope.facturaLibertador = datos.data;
$scope.tableFacturaLibertador.reload();
});
});
NOTE: if i write $rootScope.on it execute 3 times. so in $scope just make one loop.
I hope this will be helpul to someone.

Angular Service throws exception when returning a promise

In my app.js code I'm running some init code which pulls session vars from the server.
Good so far; however I'm now trying to add an additional call to pull data for a treeview widget. This new call is causing the JavaScript exception :
"Cannot read property 'then' of undefined"
The startup code is:
1) app.run gets called first,
2) call into 'userService' to init various $rootScope vars
3) userService makes API calls to a server and returns data. $q.defer() and $http is used
** NEXT STEPS CAUSES AN EXCEPTION
4) call into userService.getUserReportsTreeFromDataContext() from app.run
5) userService.getUserReportsTreeFromDataContext then calls down into datacontext.js (THIS SOMEHOW CAUSES AN EXCEPTION).
Here is my app.run() code within app.so
app.run(['$route', '$rootScope', 'common', 'userService', function ($route, $rootScope, common, userService) {
// initialize session vars
userService.openUserSession(razorEnvJson).then(function (data) {
var sessionID = data.data[0];
$rootScope.rageSessionVars.sessionID = sessionID;
// **** THROWS EXCEPTION HERE ****
userService.getUserReportsTreeFromDataContext().then(function (data){
// var myData = data;
});
});
}]);
and a snippet from userContext.js service :
this.openUserSession = function (razorEnvParams) {
_razorEnvParams = razorEnvParams;
_// some vars ommitted here for brevity
var url = "http://" + _domain + ":" + _port + controllerpath + "?userid=" + user + "&pass=" + pass;
var deferred = $q.defer();
deferred.notify("Opening user session...");
var retval = [];
$http({
method: 'GET',
encoding: 'JSON',
headers: {
'Access-Control-Allow-Origin': 'true',
'Content-Type': 'application/json'
},
withCredentials: true,
url: url
}).success(function (data, status, headers, config) {
retval = data;
deferred.resolve(retval);
}).error(function (data, status, headers, config) {
log("Cannot open a user session via api call. Errors details: " + data);
});
return deferred.promise;
}
this.getUserReportsTreeFromDataContext = function (userID) {
datacontext.getReportsTree().then(function (data) {
return data;
});
}
and my datacontext.js code to pull data from server, or to pull some test data :
(function () {
'use strict';
var serviceId = 'datacontext';
angular.module('app').factory(serviceId, ['$http', '$rootScope', 'common', datacontext]);
function datacontext($http, $rootScope, common) {
var $q = common.$q;
var service = {
getReportsTree: getReportsTree,
sendAggrRequestToServer: sendAggrRequestToServer,
};
return service;
function getReportsTree() {
var reportsJson = [
{
id: 1, text: "Standard", expanded: false, spriteCssClass: "rootfolder", checkChildren: true, items: [
{ id: 3, text: "MTM Aggr", reptName: "MTM Aggr" },
{ id: 4, text: "Member Aggr", reptName: "Member Aggr" }
]
},
{
id: 30, text: "Hierarchy", expanded: false, spriteCssClass: "rootfolder", checkChildren: true, items: [
{ id: 31, text: "Ctpy Hrchy", reptName: "CTPYHIER", withHierarchy: 'true' },
{ id: 32, text: "Ctpy/BkgLocation Hrchy", reptName: "CTPYHIER_BKG_LOC", withHierarchy: 'true' }
]
}
];
return $q.when(reportsJson);
}
})(); // end datacontext.js
FYI - I make many other successful calls from my dashboard.js controller into datacontext.js with no problems.
Here's a good example, where some test data is pulled from datacontext :
dashboard.js -
function getPositionsData() {
datacontext.getPositions().then(function (data) {
vm.positionsData = data;
populateGridDataSource(vm.positionsData);
});
}
datacontext.js -
function getPositions() {
var positionsJson = [
{ id: 1, product: "BAX", instrument: "BOND-0003", position: 11, delta: 0.02, gamma: 0.79, initMarin: 600, initMarginPctChange: 250, varMargin: 75 },
{ id: 2, product: "BAX", instrument: "BOND-0004", position: -4, delta: 0.12, gamma: 0.46, initMarin: 400, initMarginPctChange: 300, varMargin: 65 },
{ id: 3, product: "BAX", instrument: "BOND-0004", position: 9, delta: 0.09, gamma: 0.55, initMarin: 700, initMarginPctChange: 200, varMargin: 40 }
];
return $q.when(positionsJson);
}
you forgot to return your initial promise in the getUserReportsTreeFromDataContext function: should be like this:
this.getUserReportsTreeFromDataContext = function (userID)
{ return datacontext.getReportsTree()
.then(function (data) { return data; });
}

Cannot reload data in Fuelux Datagrid

I have tried to reload the data populated by an ajax call but I cant get it to work, it shows the old data even after using the reload method. The thing is that if I change some variables to populate a different data and try to call the following code without refreshing the page it does not reload the updated data =/ Here is my code:
function populateDataGrid() {
$.ajaxSetup({async: false});
var gridinfo="";
$.post("lib/function.php",{activity: activity, shift: shift, date: date},
function (output){
gridinfo = JSON.parse(output);
});
$.ajaxSetup({async: true});
// INITIALIZING THE DATAGRID
var dataSource = new StaticDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) {
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
data: gridinfo,
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-fast-appointment-results').modal({show:true});
}
I found a solution... I had to create a new DataSource (lets call it "AjaxDataSource") and add the ajax request functionality within the data constructor:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['underscore'], factory);
} else {
root.AjaxDataSource = factory();
}
}(this, function () {
var AjaxDataSource = function (options) {
this._formatter = options.formatter;
this._columns = options.columns;
this._delay = options.delay || 0;
this._data = options.data;
};
AjaxDataSource.prototype = {
columns: function () {
return this._columns;
},
data: function (options, callback) {
var self = this;
setTimeout(function () {
var data;
$.ajax({
url: 'getdata.php',
type: 'POST',
data: 'param1:param1,param2,param2,...,paramN:paramN', // this is optional in case you have to send some params to getdata.php
dataType: 'json',
async: false,
success: function(result) {
data = result;
},
error: function(data){
//in case we want to debug and catch any possible error
// console.log(data);
}
});
// SEARCHING
if (options.search) {
data = _.filter(data, function (item) {
var match = false;
_.each(item, function (prop) {
if (_.isString(prop) || _.isFinite(prop)) {
if (prop.toString().toLowerCase().indexOf(options.search.toLowerCase()) !== -1) match = true;
}
});
return match;
});
}
var count = data.length;
// SORTING
if (options.sortProperty) {
data = _.sortBy(data, options.sortProperty);
if (options.sortDirection === 'desc') data.reverse();
}
// PAGING
var startIndex = options.pageIndex * options.pageSize;
var endIndex = startIndex + options.pageSize;
var end = (endIndex > count) ? count : endIndex;
var pages = Math.ceil(count / options.pageSize);
var page = options.pageIndex + 1;
var start = startIndex + 1;
data = data.slice(startIndex, endIndex);
if (self._formatter) self._formatter(data);
callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
}, this._delay)
}
};
return AjaxDataSource;
}));
After defining the new DataSource, we just need to create it and call the datagrid as usual:
function populateDataGrid(){
// INITIALIZING THE DATAGRID
var dataSource = new AjaxDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) { // in case we want to add customized items, for example a button
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-results').modal({show:true});
}
So now we have our datagrid with data populated via ajax request with the ability to reload the data without refreshing the page.
Hope it helps someone!

next page button on ng-grid does a post

I've created my first ng-grid table and loading it with data asynchronously from the server. All my code seems to get executed created and function as desired behind the scenes except for one major problem.
ng-grid's pagination buttons get rendered in HTML as 'button' tags like this:
<button class="ngPagerButton" ng-click="pageForward()" ng-disabled="cantPageForward()" title="Next Page">
<div class="ngPagerLastTriangle ngPagerNextTriangle"></div>
</button>
But there is no type attribute put on the button so it defaults to type='submit'.
Whenever I click on the next page button, behind the scenes everything works, but it also does an extraneous POST because of the button type. This is completely undesired.
Anyone else run into this? How do you get around it? Am I doing something wrong?
The basic setup is as follows:
HTML:
<div id='deposits' class='gridStyle' ng-grid='gridOptions'></div>
JS controller code (really nothing special here, taken pretty much right from the ng-grid docs...but not working!):
$scope.reportingForm = {
startDate: new Date(2014, 1, 1), // just for testing
endDate: new Date(2014, 1, 7),
};
$scope.filterOptions = {
filterText: '',
useExternalFilter: true
};
$scope.totalServerItems = 0;
$scope.pagingOptions = {
pageSizes: [7, 14],
pageSize: 7,
currentPage: 1
};
$scope.setPagingData = function(data, page, pageSize) {
var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
$scope.data = pagedData;
$scope.totalServerItems = data.length;
if (!$scope.$$phase) {
$scope.$apply();
}
};
$scope.getPagedDataAsync = function(pageSize, page, searchText) {
setTimeout(function () {
var data;
if (searchText) {
var filter = searchText.toLowerCase();
myService.getDataAsync(
$scope.reportingForm.startDate, $scope.reportingForm.endDate
function(result) {
data = result.result.data.filter(function(item) {
return JSON.stringify(item).toLowerCase().indexOf(filter) != -1;
});
$scope.setPagingData(data, page, pageSize);
}
);
} else {
myService.getDataAsync(
$scope.reportingForm.startDate, $scope.reportingForm.endDate,
function(result) {
$scope.setPagingData(result.result.data, page, pageSize);
}
);
}
}, 100);
};
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
$scope.$watch('pagingOptions', function (newVal, oldVal) {
if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}
}, true);
$scope.$watch('filterOptions', function (newVal, oldVal) {
if (newVal !== oldVal) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}
}, true);
$scope.gridOptions = {
data: 'data',
pagingOptions: $scope.pagingOptions,
filterOptions: $scope.filterOptions,
enablePaging: true,
showFooter: true,
columnDefs: [
{ field: 'date', displayName: 'Date' },
{ field: 'id', displayName: 'Id' },
{ field: 'location', displayName: 'Location' },
{ field: 'amount', displayName: 'Amount' },
]
};
ng-grid renders the previous and next page buttons as <button> and does not specify a button type so it defaults to type='submit'.
In our page the ng-grid table lived within a form. I didn't know this but after some testing realized submit <button>s within a form do a POST, but submit <button>s outside of a form do NOT do a POST.
By moving our ng-grid table outside of the form we no longer have this problem.
Really though, this seems to be an oversight in the ng-grid code. It should really be rendering the buttons as type='button' to prevent this kind of issue in the future. I can't imagine any cases where you'd want the last/next page buttons to do POSTs.
This appears to have been fixed in ng-grid 2.0.8 whenever it is released.
https://github.com/angular-ui/ng-grid/pull/693

Extjs drag and drop single item on grid with checkbox model

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.

Categories

Resources