Combine two DataTable Columns into one using Javascript - javascript

I'm currently working with Groovy/Grails and Javascript.
The code I am currently working with doesn't seem to follow a standard of how DataTables are implemented (at least not what I can see; I'm new to using DataTables and I can't find anything that is similar to what I'm seeing)
I need to combine the Survey Name and Type columns into a single column.
Example data within the "Survey Name / Type" column: "This is my Survey Name (Type)"
Controller:
The Table definitions are declared in the Controller. I'm not quite sure why they are defined here rather than on the gsp...
def impTableConfigs = [
id: [ title: '', sortIndex: 'id', visible: false ],
surveyId: [ title: 'Survey ID Number', sortIndex: 'surveyId', visible: true ],
surveyName: [ title: 'Survey Name', sortIndex: 'surveyName', visible: true],
type: [ title: 'Survey Type', sortIndex: 'type.code', visible: true]
]
def imp = {
// Check is user is logged in
// Check the users role
def dataMemberNames = getDataMemberNames(impTableConfigs)
def editingShtuff = userService.getUserEditing()
withFormat{
html{
return [
title: "Surveys",
editingShtuff : editingShtuff ,
selectedRefugeId: params.filter,
colNames: dataMemberNames,
colTitles: dataMemberNames.collect{
impTableConfigs[it]["title"]
}
]
}
json{
def args = getListDataParams(impTableConfigs, dataMemberNames, editingShtuff)
def results = getFormattedImpListData(
impTableConfigs,
editingShtuff ,
args.refuge,
args.max,
args.offset,
args.sort,
args.sortDir
)
render results as JSON
}
}
}
GSP
$(document).ready(function() {
var ops = {
editAction:'${createLink(controller:"survey", action:"edit")}',
source:'${createLink(controller:"report", action:"imp.json")}?filter='+$("#filter option:selected").val(),
swfUrl:'${resource(dir:'css/data-tables-tabletools',file:'copy_csv_xls_pdf.swf')}',
colNames:<%= colNames as JSON %>,
selectable: false,
useCache: false,
csvAction: '${createLink(action:"imp_download_csv")}',
pdfAction: '${createLink(action:"imp_download_pdf")}',
csvParams: getFilterParam,
pdfParams: getFilterParam
};
// Initialize dataTable
var table = new primr.dataTable("#dataTable", ops, {
aoColumnDefs: [ { aTargets: [8], bSortable: false }]
});
window.table = table;
// Connect filter events
$("#filter").change(function(){
var filter = $("#filter option:selected").val();
table.changeSource("${createLink(controller:"report", action:"imp.json")}?filter=" + filter);
})
});
HTML within the GSP
<table id="dataTable">
<thead>
<tr>
<g:each in="${colTitles}" var="it" status="i">
<th>${it}<sup>${i}</sup></th>
</tr>
</thead>
<tbody>
</tbody>
I'm thinking I need to move the column definitions from the Controller to the GSP and put them in the aoColumnDefs and formatting the surveyName to concatonate the 2 columns together? I'm hesistent to do this, however, as the impTableConfigs variable is used in multiple methods within the Controller. (I've included one such method).

Nevermind, I had already solved the issue but my browser was caching the domain object and controllers.
I put a getter in the Domain Object to concatonate the column values and put it in the impTableConfigs
def impTableConfigs = [
id: [ title: '', sortIndex: 'id', visible: false ],
surveyId: [ title: 'Survey ID Number', sortIndex: 'surveyId', visible: true ],
surveyNameAndType: [title: 'Survey Name/(Type)', sortIndex: 'surveyName', visible: true],
//surveyName: [ title: 'Survey Name', sortIndex: 'surveyName', visible: true ],
//type: [ title: 'Survey Type', sortIndex: 'type.code', visible: true ],
]

Related

How to create a dynamic (on the fly) form in Sencha Touch

I am working in a sencha touch ap and I need to generate views with dynamic forms.
Configuration comes from the backend (JSON) and depending of this I paint a component or other.. for example:
"auxiliaryGroups": [
{
"id": "1000",
"name": "Basic Data",
"fields": [
{
"id": "1001",
"name": "Company name",
"editable": true,
"mandatory": true,
"calculation": true,
"internalType": "T",
"type": "textfield",
"options": []
}
]
}
],
Where type is related xtype in Sencha.
In the view I am creating all options of fields:
{
xtype : 'fieldset',
itemId: 'auxiliaryFieldsGroup3',
title: 'Requirements',
//cls : 'headerField',
items:[
{
xtype: 'togglefield',
name: 'f6',
label: 'Auxiliary field R1'
},
{
xtype: 'selectfield',
name: 'f10',
label: 'Auxiliary field R5',
placeHolder: 'Select one..',
options: [
{text: 'First Option', value: 'first'},
{text: 'Second Option', value: 'second'},
{text: 'Third Option', value: 'third'}
]
},
{
xtype: 'textfield'
}
]
}
And I receive the configuration from the server, I understand the view like a store of different fields, and from the controller, it should add only fields specified in the json object.
How to create this dynamically following MVC concept?
Thank you
I assume that you have all the fields in the auxiliaryGroups.fields array.
After loading the form data from AJAX you can do it like this in your success call.
succses:function(response){
var response = Ext.decode(response.responseText);
var fields = response.auxiliaryGroups.fields;
var form = Ext.create("Ext.form.Panel",{
// here your form configuration.
cls:"xyz"
});
Ext.Array.forEach(fields,function(field){
var formField = {
xtype: field.type,
label: field.name,
name: field.id
};
form.add(formField);
});
Ext.Viewport.add(form);
form.show();
}
Based on my comment on your question, my idea about dynamic form generation is using ExtJS syntax to load form definition would be something like the code below; of course it would be extended and the data can be loaded from the server.
Ext.require([
'Ext.form.*'
]);
Ext.onReady(function() {
var data = [{
fieldLabel: 'First Name',
name: 'first',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'last'
}, {
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype: 'email'
}, {
xtype: 'timefield',
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
}];
var form = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Simple Form',
bodyStyle: 'padding:5px 5px 0',
width: 350,
fieldDefaults: {
msgTarget: 'side',
labelWidth: 75
},
defaultType: 'textfield',
defaults: {
anchor: '100%'
}
});
form.add(data);
form.render(document.body);
});
update:
When you create a view in run-time, communication between view and controller might be problematic because the controller doesn't know anything about the view. considering that the controller is responsible for initializing the view with appropriate data and handling view's events, data binding mechanism in ExtJS can solve the first part (initializing the view) which is described at View Models and Data Binding, the second part (handling view's events) can be solved with general methods in the controller, every element in the view should send its event to some specific methods and the methods based on the parameters should decide what to do.
This approach makes your methods in the controller a little fat and complicated that is the price of having dynamic form.
It is worth to mention that EXTJS raises different events in the life cycle of controllers and views and you should take benefit of them to manage your dynamic form.
I don't know about Touch, but in ExtJS, I usually do it by using the add function of a fieldset. You just loop through all your records, and create the fields on the fly.
var field = Ext.create('Ext.form.field.Text'); //or Ext.form.field.Date or a number field, whatever your back end returns.
Then set correct config options on field then
formFieldset.add(field);

Can only edit last row of Dojo DataGrid

I am using a dojo datagrid that is displaying data either coordinate data sent from a server, or coordinate data from pins which are added to an ESRI map.
However, when I click on a cell to edit the text box displays and you can change the value yet the change does not save unless you are editing the final row. If you edit a text box in row 2 and then click the box in the same column for the final row, the row 2 value is put in the final row.
If you exit any other way row 2 data reverts back to its original value. The final row behaves exactly how I want it to, you can edit all the values and they are saved (unless page is refreshed). If another row is added, and you try to edit it the row will throw a
"Uncaught TypeError: Cannot read property 'get' of undefined " error on ObjectStore.js:8.
I started with the code from the hellodgrid example
http://dojotoolkit.org/documentation/tutorials/1.9/working_grid/demo/ using the "Editing data with the Grid" and edited columns in any row.
I haven't seen a problem that's anything like mine and I am really stumped, so any help is appreciated.
Data in the following code is an array of objects I created.
function drawTable(data){
require([
"dojox/grid/DataGrid",
"dojox/grid/cells",
"dojox/grid/cells/dijit",
"dojo/store/Memory",
"dojo/data/ObjectStore",
"dojo/date/locale",
"dojo/currency",
"dijit/form/DateTextBox",
"dojox/grid/_CheckBoxSelector",
"dojo/domReady!"
], function(DataGrid, cells, cellsDijit, Memory, ObjectStore, locale, currency,
DateTextBox, _CheckBoxSelector){
function formatDate(inDatum){
return locale.format(new Date(inDatum), this.constraint);
}
gridLayout = [
{
type: "dojox.grid._CheckBoxSelector",
defaultCell: { width: 8, editable: true, type: cells._Widget, styles: 'text-align: right;' }
},
//cells:
[
{ name: 'Number', field: 'order', editable: false /* Can't edit ID's of dojo/data items */ },
{ name: 'ID', field: 'uniqueID', width: 10, editable: false /* Can't edit ID's of dojo/data items */ },
{ name: 'Station ID', field: 'stationID', width: 15, editable: true },
/* No description for each station... at least not yet
{ name: 'Description', styles: 'text-align: center;', field: 'description', width: 10,
type: cells.ComboBox,
options: ["normal","note","important"]},*/
{ name: 'Road', field: 'road', width: 10, editable: true, styles: 'text-align: center;',
type: cells.CheckBox},
{ name: 'Route', field: 'route', width: 10, editable: true, styles: 'text-align: center;',
type: cells.CheckBox},
{ name: 'Count Type', width: 13, editable: true, field: 'countType',
styles: 'text-align: center;',
type: cells.Select,
options: ["new", "read", "replied"] },
{ name: 'Count Duration', field: 'countDuration', styles: '', width: 15, editable: true},
/*
May want to use this later
{ name: 'Date', field: 'col8', width: 10, editable: true,
widgetClass: DateTextBox,
formatter: formatDate,
constraint: {formatLength: 'long', selector: "date"}}, */
]
//{
];
objectStore = new Memory({data:data});
stationGridStore = new ObjectStore({objectStore: objectStore});
// create the grid.
grid = new DataGrid({
store: stationGridStore,
structure: gridLayout,
// rowSelector: '20px',
"class": "grid"
}, "grid");
grid.startup();
// grid.canSort=function(){return false;};
});
}
You haven't included your actual data in the question, but based on one of your columns, I am guessing your data items store a unique identifier in a property called uniqueID. However, dojo/store/Memory by default assumes that unique IDs are in the id property. That mismatch may very well be what's causing your issue.
You can inform dojo/store/Memory that your unique identifiers are under another property by setting idProperty on the instance:
objectStore = new Memory({ data: data, idProperty: 'uniqueID' });

Selecting rows from one grid & passing them to another grid

I'm trying to allow rows to be selected via checkboxes and for those selected rows and their IDs to be sent to another grid when a 'Submit' button is clicked. In other words, acting as some sort of filter.
I've contacted Telerik's support team and was advised to take the following steps in order to get it working:
Get the selected rows with the Select() method of the Grid
Loop through them & get the underlying item with the dataItem method
Save them into an array
Destroy the grid
Initialize a new grid by setting the data data
Here's a sample on JSBin that shows what I have in mind.
I'm not sure where to start honestly. I would really appreciate it if someone could point me in the right direction to any resources or guides that would be helpful. Thanks!
Assuming you are using RadGrid, make sure you have client side selection turned on, you would see something like this:
<ClientSettings>
<Selecting AllowRowSelect="True" />
<ClientEvents OnRowSelected="RowSelected" />
</ClientSettings>
On the input button, make sure to call your JS method as follows :
<input onclick="GetSelected();" .... >
Your JS code might look something like this :
function GetSelected() {
var grid = $find("<%=Your Grid's ClientID Here%>");
var MasterTable = grid.get_masterTableView();
var selectedRows = MasterTable.get_selectedItems(); // 1. Get the selected rows. The selected item can be accessed by calling the get_selectedItems() method of the GridTableView client-side object.
for (var i = 0; i < selectedRows.length; i++) {
var row = selectedRows[i];
// This is where you would have to insert it in a collection so that you can bind it to another grid... You will need to call .Rebind() once you assign the new datasource to the other grid.
}
Hopefully this will give you some idea.. I can see if I can find any examples on inserting rows into other grid if you get stuck.
check this code
html
<div id="grid1"></div>
<input type="button" value="Submit" onclick="Move()" />
<div id="grid2" ></div>
script
<script>
$(document).ready(function() {
var data1 = [
{ id: 1, rating: 3, year: 1997, title: "Rock" }
, { id: 2, rating: 5, year: 1999, title: "X-Man" }
, { id: 3, rating: 4, year: 2011, title: "World War Z" }
];
var grid1=$("#grid1").kendoGrid({
sortable: true
, silectable: true
, selectable: "multiple row"
, filterable: true
, pageable: true
, columns: [
{ template: "<input type='checkbox' class='checkbox' />", width: "40px" }
,{ field: "id", title: "Id", filterable: false }
, { field: "rating", title: "Rating", filterable: false }
, { field: "year", title: "Year", filterable: true, type: "string"}
, { field: "title", title: "Title" }
]
, dataSource: { page: 1,
pageSize: 5,
data: data1
}
}).data("kendoGrid");
grid1.table.on("click", ".checkbox", selectRow);
var data2 = [
{ id: 101, rating: 6, year: 2012, title: "The Impossible" }
, { id: 102, rating: 8, year: 2013, title: "Escape" }
, { id: 103, rating: 7, year: 2013, title: "Gravity" }
];
$("#grid2").kendoGrid({
sortable: true
, silectable: true
, selectable: "multiple row"
, filterable: true
, pageable: true
, columns: [
{ field: "id", title: "Id", filterable: false }
, { field: "rating", title: "Rating", filterable: false }
, { field: "year", title: "Year", filterable: true, type: "string"}
, { field: "title", title: "Title" }
]
, dataSource: { page: 1,
pageSize: 5,
data: data2
}
});
});
function Move() {
var grid1 = $("#grid1").data("kendoGrid");
var rows = grid1.select();
rows.each(function(index, row) {
var selectedRow = grid1.dataItem(row);
//-move to grid2
var grid2 = $("#grid2").data("kendoGrid");
var ins = { id: selectedRow.id, rating: selectedRow.rating, year: selectedRow.year, title: selectedRow.title }; //id=1,rating=9.2,year=1995,title="The Godfather"
grid2.dataSource.insert(ins);
});
rows.each(function() {
grid1.removeRow($(this).closest('tr'));
});
}
function selectRow() {
var checked = this.checked,
row = $(this).closest("tr");
if (checked) {
//-select the row
row.addClass("k-state-selected");
} else {
//-remove selection
row.removeClass("k-state-selected");
}
}
</script>
this will help you :)

ExtJS 4.1 Infinite Grid Scrolling doesnt work with Dynamic store using loadData

I have to load first grid panel on tab and then load data into store using loadData() function which is working fine, but now I have to integrate infinite grid scrolling with it.
Is there any way to integrate infinite scrolling on fly after loadData into store..? I am using ExtJS 4.1. Please help me out.
Here I am showing my current script in controller and grip view panel in which I have tried out but not working.
Controller Script as below:
var c = this.getApplication().getController('Main'),
data = c.generateReportGridConfiguration(response,true),
tabParams = {
title: 'Generated Report',
closable: true,
iconCls: 'view',
widget: 'generatedReportGrid',
layout: 'fit',
gridConfig: data
},
generatedReportGrid = this.addTab(tabParams);
generatedReportGrid.getStore().loadData(data.data);
On Above script, once I get Ajax call response, adding grid panel with tabParams and passed data with gridConfig param which will be set fields and columns for grid and then last statement supply grid data to grid. I have tried out grid panel settings by following reference example:
http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/infinite-scroll.html
On above page, Included script => http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/infinite-scroll.js
My Grid Panel Script as below:
Ext.define('ReportsBuilder.view.GeneratedReportGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.generatedReportGrid',
requires: [
'ReportsBuilder.view.GenerateViewToolbar',
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.grid.PagingScroller',
'Ext.grid.RowNumberer',
],
initComponent: function() {
Ext.define('Report', {extend: 'Ext.data.Model', fields: this.gridConfig.fields, idProperty: 'rowid'});
var myStore = Ext.create('Ext.data.Store', {model: 'Report', groupField: 'name',
// allow the grid to interact with the paging scroller by buffering
buffered: true,
pageSize: 100,
autoSync: true,
extraParams: { total: 50000 },
purgePageCount: 0,
proxy: {
type: 'ajax',
data: {},
extraParams: {
total: 50000
},
reader: {
root: 'data',
totalProperty: 'totalCount'
},
// sends single sort as multi parameter
simpleSortMode: true
}
});
Ext.apply(this, {
dockedItems: [
{xtype: 'generateviewToolbar'}
],
store: myStore,
width:700,
height:500,
scroll: 'vertical',
loadMask: true,
verticalScroller:'paginggridscroller',
invalidateScrollerOnRefresh: false,
viewConfig: {
trackOver: false,
emptyText: [
'<div class="empty-workspace-bg">',
'<div class="empty-workspace-vertical-block-message">There are no results for provided conditions</div>',
'<div class="empty-workspace-vertical-block-message-helper"></div>',
'</div>'
].join('')
},
columns: this.gridConfig.columns,
features: [
{ftype: 'groupingsummary', groupHeaderTpl: '{name} ({rows.length} Record{[values.rows.length > 1 ? "s" : ""]})', enableGroupingMenu: false}
],
renderTo: Ext.getBody()
});
// trigger the data store load
myStore.guaranteeRange(0, 99);
this.callParent(arguments);
}
});
I have also handled start and limit from server side query but it will not sending ajax request on scroll just fired at once because pageSize property in grid is 100 and guaranteeRange function call params are 0,99 if i will increased 0,299 then it will be fired three ajax call at once (0,100), (100,200) and (200,300) but showing data on grid for first ajax call only and not fired on vertical scrolling.
As, I am new learner on ExtJs, so please help me out...
Thanks a lot..in advanced.
You cannot call store.loadData with a remote/buffered store and grid implementation and expect the grid to reflect this new data.
Instead, you must call store.load.
Example 1, buffered store using store.load
This example shows the store.on("load") event firing.
http://codepen.io/anon/pen/XJeNQe?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var store = Ext.create("Ext.data.Store", {
fields: ["id", "name"]
,buffered: true
,pageSize: 100
,proxy: {
type: 'rest'
,url: '/anon/pen/azLBeY.js'
reader: {
type: 'json'
}
}
})
store.on("load", function(component, records) {
console.log("store.load")
console.log("records:")
console.log(records)
})
var grid = new Ext.create("Ext.grid.Panel", {
requires: ['Ext.grid.plugin.BufferedRenderer']
,plugins: {
ptype: 'bufferedrenderer'
}
,title: "people"
,height: 200
,loadMask: true
,store: store
,columns: [
{text: "id", dataIndex: "id"}
,{text: "name", dataIndex: "name"}
]
})
grid.on("afterrender", function(component) {
console.log("grid.afterrender")
})
grid.render(Ext.getBody())
store.load()
})
})(Ext)
Example 2, static store using store.loadData
You can see from this example that the store.on("load") event never fires.
http://codepen.io/anon/pen/XJeNQe?editors=001
;(function(Ext) {
Ext.onReady(function() {
console.log("Ext.onReady")
var store = Ext.create("Ext.data.Store", {
fields: ["id", "name"]
,proxy: {
type: 'rest'
,reader: {
type: 'json'
}
}
})
store.on("load", function(component, records) {
console.log("store.load")
console.log("records:")
console.log(records)
})
var grid = new Ext.create("Ext.grid.Panel", {
title: "people"
,height: 200
,store: store
,loadMask: true
,columns: [
{text: "id", dataIndex: "id"}
,{text: "name", dataIndex: "name"}
]
})
grid.on("afterrender", function(component) {
console.log("grid.afterrender")
})
grid.render(Ext.getBody())
var data = [
{'id': 1, 'name': 'Vinnie'}
,{'id': 2, 'name': 'Johna'}
,{'id': 3, 'name': 'Jere'}
,{'id': 4, 'name': 'Magdalena'}
,{'id': 5, 'name': 'Euna'}
,{'id': 6, 'name': 'Mikki'}
,{'id': 7, 'name': 'Obdulia'}
,{'id': 8, 'name': 'Elvina'}
,{'id': 9, 'name': 'Dick'}
,{'id': 10, 'name': 'Beverly'}
]
store.loadData(data)
})
})(Ext)

How to remotely sort an Ext grid column that renders a nested object?

Simple question here, and I'm really surprised I cannot find an answer to it anywhere.
I have the following product model:
Ext.define('Product', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'manufacturer', type: 'auto'}, // i.e. nested object literal
],
});
As can be seen, a product has a nested object inside it that contains details about a manufacturer (id, name, description, etc.).
I display products in an Ext.grid.Panel, like so:
Ext.create('Ext.grid.Panel', {
title: 'Products',
...
remoteSort: true,
columns: [
{text: 'Id', dataIndex: 'id', sortable: true},
{text: 'Name', dataIndex: 'name', sortable: true},
{text: 'Manufacturer', dataIndex: 'manufacturer', sortable: true, renderer: function(manufacturer) {
return manufacturer.name; // render manufacturer name
}
},
],
});
As you can see, all three columns are configured to be sortable, and I am using remote sorting. This works for the first two columns, but the third column (manufacturer) is giving me trouble.
For instance, when a user sorts the grid by product name, Ext sends the following JSON to the server:
{ sort: [{ property: 'name', direction: 'ASC' }] }
This is fine, because the server knows to simply sort by each product's name property.
But when a user sorts the grid by manufacturer, the JSON sent is:
{ sort: [{ property: 'manufacturer', direction: 'ASC' }] }
Since the manufacturer is an object, this does not give the server any idea which property of the manufacturer it should sort by! Is it the manufacturer's id? Or is it the manufacturer's name? Or something else?
For my grid, since I render the manufacturer's name, I'd like to sort it by name. But I see no way to tell the server this. And I certainly don't want to make my server just sort by the manufacturer's name all the time.
If the JSON was sent like this it would be ideal:
{ sort: [{ property: 'manufacturer.name', direction: 'ASC' }] }
Sadly, Ext does not seem to do that (?). So, what's the solution?
Okay, I asked on the Sencha Forums and got a response. It appears you can override getSortParam() in the column config. Example:
columns: [
...
{
header: 'Manufacturer',
dataIndex: 'manufacturer',
sortable: true,
renderer: function(manufacturer) {
return manufacturer.name; // render manufacturer name
},
getSortParam: function() {
return 'manufacturer.name';
},
}
...
]
This will send the ideal JSON I described in my OP. Now I just need to make my server parse this properly! :)

Categories

Resources