I have an application showing two datatables. Both tables use the button extension to support a column visibility dialog.
The second table has a first column without title. In the column visibility Dialog the button should have a title, that is why i override the columnText function of the colvis extension
var buttons= [{
extend: 'colvis',
postfixButtons: ['colvisRestore'],
collectionLayout: 'fixed three-column'
}];
if("secondTable" === tableName) {
buttons[0]['columnText'] = function (dt, idx, title) {
if (idx === 0) {
return "firstColumnTitle";
} else {
return title;
}
};
//add default buttons to buttons
buttons[0]['buttons'] = [{extend: 'columnsToggle'}];
//add one extra button to the collection
buttons[0]['buttons'].push([
{
extend: 'columnToggle',
text: 'HR',
columns: [1, 2]
}]);
}
DataTable({
rowId: 'id',
ajax: 'content.do',
buttons: buttons
});
I would expect to have the columntext function called for second table only
if i add buttons the columnText function is no longer called. Why?
Thanks to the comments above #davidkonrad and #Adelin. If found the reason.
instead of assigning the columnText function to the colvis extension, i need to assign it to the columnsToggle Extension inside.
if("secondTable" === tableName) {
//add default buttons to buttons
buttons[0]['buttons'] = [{
extend: 'columnsToggle',
columnText: function (dt, idx, title) {
if (idx === 0) {
return "firstColumnTitle";
} else {
return title;
}
}}];
//add one extra button to the collection
buttons[0]['buttons'].push([
{
extend: 'columnToggle',
text: 'HR',
columns: [1, 2]
}]);
}
Related
I am using Bootstrap Table with the Editable plugin. I have a button to add new rows to the table. I like to have the cell for the new row in the Notes column have a background color of blue.
From the documentation:
function cellStyle(value, row, index, field) {
return {
classes: 'text-nowrap another-class',
css: {"color": "blue", "font-size": "50px"}
};
}
The only thing that is consistent with those parameters and adding a new row is the index = 0, so I default all the others to Null. It seems like my function is not even being called. I'm new to JavaSript so I might just be missing something.
http://jsfiddle.net/8gk0ogtp/1/
$button = $('#button');
$(function () {
$button.click(function () {
$table.bootstrapTable('insertRow', {
index: 0,
row: {}
});
cellStyle();
});
});
function cellStyle1(value=Null, row=Null, index=0, field=Null) {
return {css: {"background-color": "blue"}}
}
Try this one
http://jsfiddle.net/bitriddler/qjht8stb/
Changes:
When adding new rows I added paintBlue=true
Updated cellStyle to this
function cellStyle(value=Null, row=Null, index=0, field=Null) {
if(row.paintBlue) {
return {css: {"background-color": "blue"}}
}
return {};
}
Passing cellStyle function when defining columns instead of passing in html data-cell-style attribute
...
{
field: 'Notes',
sortable: 'true',
cellStyle: cellStyle,
title: 'Notes',
editable: {
type: 'textarea'
}
...
Currently, I am populating the data for my grid using XML file.
My XML file is something like this
<property>
<category>Email</category>
<name>To-address</name>
<value>abc#xyz.com</value>
</property>
<property>
<category>Email</category>
<name>From-address</name>
<value>abc#xyz.com</value>
</property>
<property>
<category>Email</category>
<name>Email-body</name>
<value>My Body</value>
</property>
<property>
<category>Email</category>
<name>Password</name>
<value>1234</value>
</property>
And I am populating my grid like this:
{
xtype: 'grid',
columns: [{
text: 'Name',
width: 100,
dataIndex: 'name'
}, {
text: 'Value',
dataIndex: 'value',
flex: 1,
getEditor: function(record) {
if (record.get('name') === 'password') {
return Ext.create('Ext.grid.CellEditor', {
field: Ext.create('Ext.form.field.Text', {
inputType: 'password'
})
})
else if (record.get('name') === 'Content') {
return Ext.create('Ext.grid.column.Action', {
width: 50,
items: [{
iconCls: 'x-fa fa-cog',
tooltip: 'Edit',
handler: function(grid, rowIndex, colIndex) {
alert('Hello World');
}
}]
});
} else {
return Ext.create('Ext.grid.CellEditor', {
field: Ext.create('Ext.form.field.Text', {})
})
},
renderer: function(value, meta, rec) {
if (record.get('name') === 'password') {
value = '***';
}
return value;
}
}
}
],
selType: 'cellmodel',
plugins: {
ptype: 'cellediting',
}
}
}
I want to add a button to the Content row as value, which will be going to pop up a window to add email body to the user on click.
This is what I tried. It is able to add a button with handler working fine, but it is hiding other grid value column data
if (record.get('name') === 'Content') {
var id = Ext.id();
Ext.defer(function() {
Ext.widget('button', {
renderTo: id,
text: 'Edit',
width: 100,
handler: function(record) {
alert("Hello world");
}
});
}, 50);
return Ext.String.format('<div id="{0}"></div>', id);
}
As a preliminary step, I want to check an alert box for the action column I am adding the content. But it is not showing up in the row.
What I am missing here to add a button to the grid row?
An editor is defined on a column, in your case, the column is of type gridcolumn (the default column type) and implicitly defined through
text: 'Value',
dataIndex: 'value',
flex: 1,
The function getEditor() of a column should return an editor component with a field derived from Ext.form.field.Base.
However, you are sometimes returning a column component from the getEditor:
getEditor: function(record){
...
else if(record.get('name') === 'Content') {
return Ext.create('Ext.grid.column.Action', {
...
This cannot work because it is the wrong component type. Also, your column has a fixed type and you cannot get a single cell of the column to behave like a different column type, except by manually overriding the renderer. I don't see a quick fix for this. You could possibly return an editor with a textfield with a trigger button inside.
However, I would recommend that you use a form for your data, which is far more suitable. In that form, you can place buttons wherever you want.
I need to employ a filter function to implement a heuristic for selecting records. Simple field/value checks, alone, are inadequate for our purpose.
I'm trying to follow the examples for function filters, but for some reason, the "allowFunctions" flag keeps getting set to false.
I attempt to set the allowFunctions property to true in the storeConfig:
storeConfig: {
models: ['userstory', 'defect'],
allowFunctions: true,
filters: [{
// This did not work ...
property: 'Iteration.Name',
value: 'Sprint 3',
// Trying dynamic Filter Function. Update: Never called.
filterFn: function (item) {
console.log("Entered Filter Function!");
var iter = item.get("Iteration");
console.log("Iteration field: ", iter);
if (iter !== null && iter !== undefined) {
return (iter.name === "Sprint 3");
} else {
return false;
}
}
}]
},
After the grid view renders, I inspect it the store configuration and its filters:
listeners: {
afterrender: {
fn: function (_myVar, eOpts) {
console.log("Arg to afterrender: ", _myVar, " and ", eOpts);
var _myStore = _myVar.getStore();
console.log("Store filters: ", _myStore.filters);
}
}
},
What I find is that the allowFunctions property has been set back to false and I see that the filter function I specified never fired.
Console Screen Shot
So either I am setting allowFunctions to true in the wrong place, or something built into the Rally Grid View and its data store prohibits filter functions and flips the flag back to false.
OR there's a third option betraying how badly off my theory of operation is.
Oh, wise veterans, please advise.
Here's the entire Apps.js file:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function () {
//Write app code here
console.log("Overall App Launch function entered");
//API Docs: https://help.rallydev.com/apps/2.1/doc/
}
});
Rally.onReady(function () {
Ext.define('BOA.AdoptedWork.MultiArtifactGrid', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function () {
console.log("onReady Launch function entered");
this.theGrid = {
xtype: 'rallygrid',
showPagingToolbar: true,
showRowActionsColumn: false,
editable: false,
columnCfgs: [
'FormattedID',
'Name',
'ScheduleState',
'Iteration',
'Release',
'PlanEstimate',
'TaskEstimateTotal',
'TaskActualTotal', // For some reason this does not display ?? :o( ??
'TaskRemainingTotal'
],
listeners: {
afterrender: {
fn: function (_myVar, eOpts) {
console.log("Arg to afterrender: ", _myVar, " and ", eOpts);
var _myStore = _myVar.getStore();
console.log("Store filters: ", _myStore.filters);
}
}
},
storeConfig: {
models: ['userstory', 'defect'],
allowFunctions: true,
filters: [{
// This did not work ...
property: 'Iteration.Name',
value: 'Sprint 3',
// Trying dynamic Filter Function. Update: Never called.
filterFn: function (item) {
console.log("Entered Filter Function!");
var iter = item.get("Iteration");
console.log("Iteration field: ", iter);
if (iter !== null && iter !== undefined) {
return (iter.name === "Sprint 3");
} else {
return false;
}
}
}]
},
context: this.getContext(),
scope: this
};
this.add(this.theGrid);
console.log("The Grid Object: ", this.theGrid);
}
});
Rally.launchApp('BOA.AdoptedWork.MultiArtifactGrid', {
name: 'Multi-type Grid'
});
});
This is a tricky one since you still want your server filter to apply and then you want to further filter the data down on the client side.
Check out this example here:
https://github.com/RallyCommunity/CustomChart/blob/master/Settings.js#L98
I think you can basically add a load listener to your store and then within that handler you can do a filterBy to further filter your results on the client side.
listeners: {
load: function(store) {
store.filterBy(function(record) {
//return true to include record in store data
});
}
}
I'm not familiar with allowFunctions, but in general remoteFilter: true/false is what controls whether the filtering is occurring server side or client side. remoteFilter: true + the load handler above gives you the best of both worlds.
I have a problem for hide/remove action column Item on record condition in grid view.
let see bellow code. there is action column code I did. I want to hide delete Icon shown in image. this delete icon hide/remove on record condition.
{
xtype: 'actioncolumn',
flex: 1,
align: 'center',
scope: this,
renderer: function (n, t, rec) {
/* if (rec.get('companyId') == 23) {
console.log('Distributor Account List');
}
else {
console.log('Distributor Client user List');
} */
},
items: [
{
icon: FLEET_SERVER_URL + 'images/edit2.png',
tooltip: fleet.Language.get('_FLEET_USER_USERLIST_EDIT_'),
handler: function (grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
this.fireEvent('showUserDetails', rec);
}
},
{
xtype: 'spacer'
},
{
icon: (Ext.getStore('userStore').first().get('issuperadmin') == 1 || Ext.getStore('userStore').first().get('isadmin') == 1 || Ext.getStore('userStore').first().get('isadmin') == 3) ?
FLEET_SERVER_URL + 'images/vehicles/van-icon.png' : '', // Use a URL in the icon config
tooltip: fleet.Language.get('_FLEET_USER_USERLIST_VEHICLE_'),
handler: function (grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
this.fireEvent('assignvehicles', rec);
}
},
{
xtype: 'spacer'
},
{
icon: FLEET_SERVER_URL + 'images/del.png',
tooltip: fleet.Language.get('_FLEET_USER_USERLIST_DELETE_'),
handler: function (grid, rowIndex, colIndex) {
Me = this;
var rec = grid.getStore().getAt(rowIndex);
Ext.Msg.show({
title: fleet.Language.get('_FLEET_USER_USERLIST_REMOVETITLE_'),
msg: fleet.Language.get('_FLEET_USER_USERLIST_REMOVEMSG_'),
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.QUESTION,
callback: function (button) {
if (button == fleet.Language.get('_FLEET_USER_USERLIST_YESBTN_')) {
Me.removeUser(rec);
}
}
});
}
}
]
}
There are 4 items in action column (Edit icon, spacer, spacer, and delete Icon) please see Attached image.
In above code there is Action column render event. e.g. I want to check record having company ID=23. I use this condition for testing. Main problem is that I want to hide that delete Icon on condition. Any proper solution for this?
What you want to do is not use the icon property, but you want to put the icons into the corresponding CSS in a class. E.g.
.someIcon {
background-image: path/to/icon.png no-repeat center center !important;
width:20px;
height:20px;
}
and then you can add a getClass config instead of the icon config, and provide the CSS classes as needed, e.g. if you want to switch icon on or off:
getClass: function(v, meta, rec) {
if(rec.get('companyId')==23) return 'someIcon';
else return '';
}
or, if you want to have different icons, e.g.:
getClass: function(v, meta, rec) {
if(rec.get('isImportant')) return 'redIcon';
else return 'greyIcon';
}
Please note that you have to recompile your project in Sencha Cmd if you add classes through SCSS.
document_table_Settings : function ()
{
return{
rowsPerPage: 5,
showNavigation: 'auto',
showColumnToggles: false,
fields: [
{key: 'para',label: 'Para',sortable: false},
{key: 'desc', label: 'Description',sortable: false},
{
key: 'rowId', label: 'Delete',sortable: false, fn: function (rowId, object) {
var html = "<button name='Del' id=" + rowId + " class='btn btn-danger'>Delete</button>"
return new Spacebars.SafeString(html);
}
},
{
key: 'rowId', label: 'Edit',sortable: false, fn: function (rowId, object) {
var html = "<button name='edit' id=" + rowId + " class='btn btn-warning'>Edit</button>"
return new Spacebars.SafeString(html);
}
}
]
};
}
I want to show description entries having show more and show less feature .As the description is long enough. so after 100 character it shows button to toggle.
If I understand you correctly, you are trying to only show the first 100 characters of the 'Description' column in the Reactive Table and then add some mechanism so that the user can click or rollover to see the entire 'Description' text.
There are a few ways to achieve this and I have provided two options below (in order of simplicity).
For a low tech rollover option, truncate the text to only show the first 100 characters, add an ellipsis (...) to the end of your text, then use the title property in a span element to show the full text on rollover.
First you will need to define a 'truncate' Template helper (I would make this a global helper so that you can use anywhere in your app).
Template.registerHelper('truncate', function(strValue, length) {
var len = DEFAULT_TRUNCATE_LENGTH;
var truncatedString = strValue;
if (length && length instanceof Number) {
len = length;
}
if (strValue.length > len) {
truncatedString = strValue.substr(1, len) + "...";
}
return truncatedString;
});
Then create a new Template for the column.
<template name="field_description">
<span title="{{data.description}}">{{truncate data.description}}</span>
</template>
And finally, change your Reactive Table configuration to use a Template.
fields: [
...,
{ key: 'desc', label: 'Description', tmpl: Template.field_description }
...,
];
For a slightly more complicated option, you can take a similar approach but add a clickable link that would show more or less detail. To get it to work you have to define a few Reactive Vars, define an event handler, and change your 'Description' Template accordingly. Here is a rough solution that should work.
Change your template like so.
<template name="field_description">
<span>{{truncatedDescription}}
{{#if showLink}}
{{linkState}}
{{/if}}
</span>
</template>
Then add the necessary logic to your field_description template (including an event handler).
import { Template } from 'meteor/templating';
import './field-description.html';
Template.field_descirption.onCreated(function() {
const MAX_LENGTH = 100;
this.description = new ReactiveVar(Template.currentData().description);
this.showMore = new ReactiveVar(true);
if (this.description.get().length > MAX_LENGTH) {
this.description.set(Template.currentData().description.substr(1, MAX_LENGTH));
}
this.showLink = () => {
return Template.currentData().description.length > MAX_LENGTH;
};
this.toggleTruncate = () => {
if (this.showMore.get()) {
this.description.set(Template.currentData().description);
this.showMore.set(false);
} else {
this.description.set(Template.currentData().description.substr(1, MAX_LENGTH));
this.showMore.set(true);
}
};
});
Template.field_descirption.helpers({
truncatedDescription: function() {
return Template.instance().description.get();
},
showLink: function() {
return Template.instance().showLink();
},
linkState: function() {
if (Template.instance().showMore.get()) {
return 'show more';
} else {
return 'show less';
}
};
});
Template.field_descirption.events({
'click .js-more-less'(event, instance) {
instance.toggleTruncate();
},
});
Lastly, make sure your Reactive Table config is still setup to use a Template for the field.
fields: [
...,
{ key: 'desc', label: 'Description', tmpl: Template.field_description }
...,
];
Note that the second option makes use of Meteor's Reactivity to solve the problem. Let me know if you need additional explanation on how the 2nd solution works.
That should do it!