Can we add a if Condition inside the column while describing the columns of the grid? Whats wrong in this code
I want to display one button in the grid under a column ,if length of the text exceeds more than 40char.
I am trying to put an if condition if the content/data is less than 40 char then display the content else display a button , On click of button open a pop-up to display the complete content inside that pop-up?
How we can put the command conditionally to display the button?
Here is my code
columns: [{
field: "id",
title: "ID",
width: "100px"
}, // fields in the grid
{
field: "name",
title: "Name",
width: "100px"
}, {
field: "remarks",
title: "Remarks",
width: "160px", // under this column button will be displayed in each
var length = 40;
if (data.remarks.length > length) { //here this condition seems to be wrong, is there any other way to display the button for this condition
command: {
name: "remarks",
text: "Remarks",
click: function (e) {
var tr = $(e.target).closest("tr");
var data = this.dataItem(tr);
var win = $('#remarksWindow');
win.html(data.remarks);
if (!win.data('kendoWindow')) {
win.kendoWindow({
width: '600px',
height: '200px',
title: 'Remarks',
actions: ['Close']
});
}
win.parent().css({
top: e.pageY - 50,
left: e.clientX - 640,
width: '600px',
height: '200px'
});
win.data('kendoWindow').open(); // open the pop-up which contains the data
return false;
}
}
}
}
},
First of all, you have a syntax error in JavaScript. Note that you can't put statements or declarations between the properties of an object:
var obj = {
a: 1,
if (true) {
b: 2;
}
}
Or
var obj = {
a: 1,
var b = 1;
}
The examples above doesn't works. So in your column property you have to use a template property:
{
field: "remarks",
title: "Remarks",
width: "160px",
template: "" // <- here goes your logic
}
So a simple template can be set as a string containing html with JavaScript logic, e.g.:
# if (remarks.length > 40) { # <input type='button' class='btn-remarks' /> # } #
Yes, you will have to set the button html by yourself. There is no way to add a condition to a command button(and that is a shame, actually).
You can check how template works here.
Then your column item should be:
{
field: "remarks",
title: "Remarks",
width: "160px",
template: "# if (remarks.length > 40) { # <input type='button' class='remarks' /> # } #"
}
Then you have to set the event for all your buttons(probably in the dataBound event):
$("#yourGrid").on("click", ".btn-remarks", function()
{
// all your click logic here
});
Give it a try and tell me what happens.
Hopefully this dojo is what you are looking for: http://dojo.telerik.com/ETora
(I have used one of Telerik's grid demos and modified to show you the principles)
The functionality you are looking for can be achieved by two means:
1) Apply a client Template to the column
2) Add a databound event that then hooks up the buttons
columns:[ {
field: "CompanyName",
title: "Company Name",
template: "#= displayTextorButton(data.CompanyName) #"
}]
function displayTextorButton(data){
var retString = '';
console.log(data);
if(data !== null && data !== undefined)
{
if(data.length > 20)
{
retString = ' <button type="button" class="btn btn-xs btn-primary"' +
'data-toggle="popover" data-placement="auto right" data-container="body" ' +
'data-content="' + kendo.htmlEncode(data) + '"' +
'data-title="Running Log Information" data-trigger="click" data-role-me="content-popover" > <span class="glyphicons glyphicons-pencil"></span> View</button>';
}
else
{
retString = '<span>' + data + '</span>';
}
}else
{
retString = '<span> - </span>';
}
return retString;
}
so the first bit I have done is added a template to the Company Name column that checks if the name is more than 20 characters if it is then it will display a button if it isn't then it will display the text as normal.
function(e){
$('button[data-role-me="content-popover"]').popover({ trigger: "focus", html: true });
}
I then hook up a databound event to the grid to then attach the event features to the "pop up" in my sample
Also note I have hooked in the bootstrap features just to make things a little easier for the demo. So this is using their popover feature. You could modify this code to work with your window.
Any issues let me know.
This is the kendo grid code
{ field: "marks", title: "marks",width: "160px",
template: function(dataItem) {
var marks = dataItem.marks;
var retString = '';
if(marks !== null && marks !== undefined)
{
if(marks.length > 40)
{
marks1 = marks.substring(0, 40)+'...';
retString1 ='<span>'+ marks1 +'</span>';
retString = retString1 + ' <button id="marksButton" type="button"' +
'data-toggle="popover" data-placement="auto right" data-container="body" ' +
'data-content="' + kendo.htmlEncode(addlRemarks) + '"' +
'data-title="marks" data-trigger="click" data-role-me="content-popover" > marks</button>';
}
else
{
retString = '<span>' + marks + '</span>';
}
}else
{
retString = '<span> - </span>';
}
return retString;
}
And its being called from a HTMl
<div class="panel-body" ng-show="accOpen[$index]">
<!-- Marks TABLE -->
<div marks-table=""
accordion-flag="accOpen[$index]"
name="name"
id="id"
>
</div>
</div>
Related
I tried removing the header in the exported PDF from the DataTable but it didn't work. Also, how to change the color table to full white and border black?
var table = $('#ReportTable').DataTable( {
lengthChange: false,
buttons: [
{"extend": 'pdf',
"className": 'btn btn-sm btn-primary rounded-pill px-3 mb-3 mb-sm-0',
customize: function(doc) {
doc.header = false;
doc.pageMargins = [ 150, 20, 150, 20 ];
},
},
{
"extend": 'print',
"className": 'btn btn-sm btn-primary rounded-pill px-3 mb-3 mb-sm-0'
},
]
} );
table.buttons().container()
.appendTo( '#ReportTable_wrapper .col-md-6:eq(0)' );
You can use title to control the title ("SiPanda") and you can use customize to control the different colors (striped lines) used for alternate rows in the PDF.
I don't want to interfere with your existing use of customize, so here is my test example which you can use as a model:
var table = $('#example').DataTable( {
dom: 'Brftip',
buttons: [
{
extend: 'pdfHtml5',
text: 'To PDF',
title: '',
customize: function ( pdf, btn, tbl ) {
delete pdf.styles.tableBodyOdd.fillColor;
}
}
]
} );
The title: '' is straightforward (assuming your PDF is actually getting its title from the web page's title).
The delete pdf.styles.tableBodyOdd.fillColor; assumes that your DataTable is using the "standard" zebra-stripes" style.
This command works because the DataTable passes the following properties to PDFMake:
tableBodyEven: Object { }
tableBodyOdd: Object { fillColor: "#f3f3f3" }
So, we remove the fillColor: "#f3f3f3" property from the tableBodyOdd object.
If you have used a different DataTables styling, you may see something different from what I see - in which case you can use console.log( pdf ); to take a closer look.
UPDATE
I missed the part about "and border black" - so here is an approach for that, also:
buttons: [
{
extend: 'pdfHtml5',
text: 'To PDF',
title: '',
customize: function ( pdf, btn, tbl ) {
delete pdf.styles.tableBodyOdd.fillColor;
pdfMake.tableLayouts = {
exampleLayout: {
hLineWidth: function (i) {
return 0.2;
},
vLineWidth: function (i) {
return 0.2;
},
hLineColor: function (i) {
return 'black';
},
vLineColor: function (i) {
return 'black';
}
//paddingLeft: function (i) {
// return i === 0 ? 0 : 8;
//},
//paddingRight: function (i, node) {
// return (i === node.table.widths.length - 1) ? 0 : 8;
//}
}
};
pdf.content[0].layout = "exampleLayout";
}
}
]
In the above snippet, I define an object called pdfMake.tableLayouts which contains a custom object called exampleLayout.
My exampleLayout defines thin black lines around every cell in the table.
I then use this custom layout by using:
pdf.content[0].layout = "exampleLayout";
You can choose your own line widths and colors.
The end result:
I am using FullCalendar 3.1.0 plugin to show events. I was able to implement multiple events with a dropdown. But user is only able to select 1 option from a single dropdown filter. My goal is to give the opportunity to select multiple options in a each dropdown filter. I am using dropdown. But when I hold down CTR and click on options, it only shows events for the first option in the list. Any help would be greatly appreciated.
Here is the HTML:
<!-- Main view: Title and calendar -->
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1 id="cal_title">Change Calendar</h1>
<div class="search_bar">
<ul id="menu">
Search By:
<li>
<select id="status_selector" multiple>
<option value="all" selected="selected">Status Types - All</option>
</select>
</li>
<li>
<select id="group_selector" multiple>
<option value="all" selected="selected">Group - All</option>
</select>
</li>
<li>
<select id="changeType_selector" multiple>
<option value="all" selected="selected">Type of Change - All</option>
<option value="6250">Emergency Change</option>
<option value="6882">Expedited Change</option>
<option value="6249">Normal Change</option>
<option value="9999">Standard Change</option>
</select>
</li>
<li>
<select id="downtime_selector" multiple>
<option value="all" selected="selected">Downtime - All</option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</li>
</ul>
</div>
<div id="calendar"></div>
<div id="footer">To ensure optimal performance, only changes created in the past 90 days are shown. For changes older than 90 days please reference EasyVista. <br />If an issue has been found and/or you have a recommendation, please open a ticket for Service Request/Applications/EasyVista - Other Request, explaining the issue or recommendation.</div>
<div id="version">SACC v2.0</div>
</div>
</div>
</div>
Here is my Javascript:
$(document).ready(function() {
/* Find all the distinct STATUS_EN and place them into a dropdown list */
// This creates first 2 dropdown dynamically
$.getJSON('json/events.json',function(json){
var usedStatus = []; // Array to keep track of all STATUS_EN that have been seen
var usedGroup = []; // Array to keep track of all group_selector that have been seen
// For each object, store the status/group in predefined variables
$.each(json, function(i,v){
// If STATUS_EN has not been seen
if (usedStatus.indexOf(v.STATUS_EN) == -1){
usedStatus.push(v.STATUS_EN); // Add STATUS_EN to usedStatus
}
// If responsible_group has not been seen
if (usedGroup.indexOf(v.responsible_group) == -1){
usedGroup.push(v.responsible_group); // Add responsible_group to usedStatus
}
});
// Sort both array variables in alphabetical order.
usedStatus.sort();
usedGroup.sort();
// Create the dropdown
usedStatus.forEach(function(value){
if (value != undefined){ // If STATUS_EN is not undefined
$("#status_selector").append('<option value="'+value+'">'+value+'</option>'); // Create an option for the dropdown list
}
});
usedGroup.forEach(function(value){
if (value != undefined){ // If responsible_group is not undefined
$("#group_selector").append('<option value="'+value+'">'+value+'</option>'); // Create an option for the dropdown list
}
});
});
/* If end_date is null, return start_date */
function isNull(end_date,start_date){
if(end_date !== null){
return end_date;
} else {
return start_date;
}
}
/* Calendar structure */
$('#calendar').fullCalendar({
/* Theme enabler */
theme: false,
/* Header description */
header: {
left: 'prev,today,next',
center: 'title',
right: 'month,basicWeek,basicDay'
},
/* Set the default view to Day */
defaultView: 'basicWeek',
/* Arrow stype (Used when theme is enabled) */
themeButtonIcons: {
prev: 'circle-triangle-w',
next: 'circle-triangle-e'
},
/* Text to show in the button */
buttonText: {
today: 'Today',
month: 'Month',
week: 'Week',
day: 'Day',
list: 'Week List'
},
navLinks: true, // Can click day/week names to navigate views
editable: false, // Remove permission to move events
eventLimit: true, // Allow "more" link when too many events
businessHours: true, // grayout afterhours
multiple: true,
/* Function that allows user to click on event. */
eventClick: function (event, jsEvent, view) {
//set the values and open the modal
$('#modalTitle').html(event.title);
$('#modalBody').html(event.text);
$('#eventUrl').attr('href', event.url);
$('#eventStatus').html("Status: " + event.STATUS_EN);
$('#fullCalModal').modal('show');
return false; // prevent from going to EasyVista right away
},
/* Function that shows description when hovering over event */
eventMouseover: function (data, event, view) {
tooltip = '<div class="tooltiptopicevent">'
+ '<strong>Request Number:</strong> ' + data.RFC_NUMBER
+ '<br /><strong>Status:</strong> ' + data.STATUS_EN
+ '<br /><strong>Start Date:</strong> ' + moment(data.start).format("MM/D, h:mm:ss a")
+ '<br /><strong>End Date:</strong> ' + moment(isNull(data.end,data.start)).format("MM/D, h:mm:ss a")
+ '<br /><strong>Description:</strong> ' + data.text + '</div>';
$("body").append(tooltip);
$(this).mousemove(function(event){
$(".tooltiptopicevent").position({
my: "left+3 bottom-3",
of: event,
collision: "flipfit"
});
});
},
/* Hide description when mouse moves out */
eventMouseout: function (data, event, view) {
$(this).css('z-index', 8);
$('.tooltiptopicevent').remove();
},
/* Feed in events from JSON file through PHP */
events: {
url: 'php/get-events.php'
},
/* Render the events */
eventRender: function eventRender(event, element, view){
return['all',event.STATUS_EN].indexOf($('#status_selector option:selected').val()) >= 0
&& ['all',event.responsible_group].indexOf($('#group_selector option:selected').val()) >= 0
&& ['all',event.change_type].indexOf($('#changeType_selector option:selected').val()) >= 0
&& ['all',event.downtime].indexOf($('#downtime_selector option:selected').val()) >= 0
},
/* Show status loading when loading */
loading: function(bool) {
$('#loading').toggle(bool);
}
});
/* Call on fullCalendar after selection of dropdown option
$('#status_selector, #group_selector, #changeType_selector, #downtime_selector').change(function() {
$('#calendar').fullCalendar('rerenderEvents');
//$('#calendar').fullCalendar('refetchEvents'); // this allows the spinner to come up each time filter is changed.
});*/
/**/
$('#status_selector, #group_selector, #changeType_selector, #downtime_selector').on('change',function(){
$('#calendar').fullCalendar('rerenderEvents');
});
});
Sample of how my .json file looks like:
[
{
"start": "2016-12-2T17:0:00",
"end": "2016-12-2T17:0:00",
"title": "12/2/2016 5:00 PM - group1",
"url": "https://sample.com",
"text": "some needed text",
"description": "description of event",
"REQUEST_ID": 462820,
"STATUS_EN": "Open",
"downtime": "No",
"change_type": "9999",
"responsible_group": "group1",
"RFC_NUMBER": "C201612_09454"
},
{
"start": "2017-2-1T21:0:00",
"end": "2017-2-1T21:0:00",
"title": "2/1/2017 9:00 PM - group2",
"url": "https://samplesite.com",
"text": "some text",
"description": "description of event",
"REQUEST_ID": 521157,
"STATUS_EN": "Closed",
"downtime": "No",
"change_type": "6250",
"responsible_group": "group2",
"RFC_NUMBER": "C201702_00976"
}
]
Doing .val() on a group of selected elements (e.g. your $('#status_selector option:selected').val()) will only return the value from the first matched element - as per the very first line of the docs: http://api.jquery.com/val/
So you need to loop through and check the values of all the selected options, and test for them individually. Something like this (untested):
eventRender: function eventRender(event, element, view){
var statusMatch = false;
var statusArr = ['all',event.STATUS_EN];
$('#status_selector option:selected').each(function(index, el)
{
if (statusArr.indexOf($(this).val()) > = 0) statusMatch = true;
});
var groupMatch = false;
var groupArr = ['all',event.responsible_group];
$('#group_selector option:selected').each(function(index, el)
{
if (groupArr.indexOf($(this).val()) > = 0) groupMatch = true;
});
var changeMatch = false;
var changeArr = ['all',event.change_type];
$('#changeType_selector option:selected').each(function(index, el)
{
if (changeArr.indexOf($(this).val()) > = 0) changeMatch = true;
});
var downtimeMatch = false;
var downtimeArr = ['all',event.downtime];
$('#downtime_selector option:selected').each(function(index, el)
{
if (downtimeArr.indexOf($(this).val()) > = 0) downtimeMatch = true;
});
return (statusMatch && groupMatch && changeMatch && downtimeMatch);
}
Using the Kendo UI tabStrip widget, I'd like to do two things:
1) auto-select the first tab, as it does not show the tab content right away.
2) Swap out the contentUrl of the first tab, under a specific condition of course.
Funny thing is, when I use the k-content-urls directive on my Html, the first tabs loads up the content right away.
ex/
<div kendo-tab-strip k-content-urls="['myTemplate.html', 'myTemplate2.html']">
However, I don't want to do it this way. I prefer the approach below, as in k-options="settings.tabOptions"
Here are the tabOptions in my controller code, and the HTML markup below it:
settings.tabOptions = {
animation: { open: { effects: "fadeIn" } },
select: function (e) {
console.log("Selected: " + e.item.innerText);
// NOT WORKING..
e.sender.dataSource.options.data[0].contentUrl = "../myNewTemplate.html"
},
change: function (e) {
console.log("Changed: ");
},
activate: function (e) {
console.log("Activated: " + e.item.innerText);
},
show: function (e) {
console.log("Shown: " + e.item.innerText);
},
contentLoad: function (e) {
console.log("Content loaded in " + e.item.innerText);
},
dataTextField: "title",
dataContentUrlField: "contentUrl",
dataSource: [{
title: "Formatting",
contentUrl: '../app/shared/include/grid-config/gad-config-grid-prop.html'
},
{
title: "Dimensions",
contentUrl: '../app/shared/include/grid-config/gad-config-grid-dimen.html'
},
{
title: "Risk Measures",
contentUrl: '../app/shared/include/grid-config/gad-config-grid-riskmeasures.html'
}],
error: function (e) {
console.log("Loading failed with " + e.xhr.statusText + " " + e.xhr.status);
}
};
<div id="Gadgettabs" kendo-tab-strip="tabstrip" k-options="settings.tabOptions">
<ul>
<li class="k-state-active">Formatting</li>
<li>Dimensions</li>
<li>Risk Measures</li>
</ul>
</div>
Again, I need to immediately show the first tab's content; and also figure out how to dynamically change out the content of the first tab.
Thanks in advance...
Bob
**** UPDATE ****
I'm trying to dynamically change the contentUrl in the select: event above but it's not working.
Final resolution:
note: if you not using "controller as" syntax in your ng-controller directive (as I am), then just replace my "settings." object with "$scope." in the controller code. And of course in the html, just remove "settings." .
// KENDO TABSTRIP
settings.urls = ['../app/shared/include/grid-config/gad-config-grid-prop.html', '../app/shared/include/grid-config/gad-config-grid-dimen.html', '../app/shared/include/grid-config/gad-config-grid-riskmeasures.html'];
if ($scope.widget.gadgetType == "chart") {
settings.urls[0] = '../app/shared/include/barchart-config/gad-config-barchart-prop.html';
};
settings.tabOptions = {
//animation: { open: { effects: "fadeIn" } },
select: function (e) {
console.log("Selected: " + e.item.innerText);
},
change: function (e) {
console.log("Changed: ");
},
activate: function (e) {
console.log("Activated: " + e.item.innerText);
},
show: function (e) {
console.log("Shown: " + e.item.innerText);
},
contentLoad: function (e) {
console.log("Content loaded in " + e.item.innerText);
},
error: function (e) {
console.log("Loading failed with " + e.xhr.statusText + " " + e.xhr.status);
}
};
<div id="Gadgettabs" kendo-tab-strip="settings.tabStrip"
k-rebind="settings.urls"
k-content-urls="settings.urls"
k-options="settings.tabOptions" >
<ul>
<li class="k-state-active">TAB1</li>
<li>TAB2</li>
<li>TAB3</li>
</ul>
</div>
I'm having trouble configuring a `Kendo UI' grid to use a DropDownList as an editor. I have a JS Bin example to reproduce my behavior. The goal is to populate the BinNumber, PartNumber and StockNumber fields once a selection is made from the dropdown. Currently I can't even get the DropDown to bind to the recordset properly. If I make a selection and move to another field, I get [object Object] in the BinNumber field. If I go back in and make another selection, the BinNumber then sticks. I have read the documentation thoroughly but I am still thoroughly confused by it.
For the [object object] mess have a look at this post, there is an attribute introduced back in late 2013 dealing with this issue data-value-primitive="true". In the past I just used to re-map the selection back to ds manually, but the attribute does it all for you, I tested in you jsBin and works fine.
binDropdownEditor: function (container, options) {
$('<input data-text-field="BinNumber" data-value-field="BinNumber" data-value-primitive="true" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList({
autoBind: false,
dataSource: viewModel.binDropDownDataSource
});
}
On change binding (please paste into your JSBin javascript tab):
var bins =["BinNumber:12121"];
var gridDS = new kendo.data.DataSource({
transport: {
read: function (e) {
e.success(bins);
}
},
schema: {
model: {
id:"Row",
fields: {
Row:{type:"string"},
BinNumber: {type:"string"},
PartNumber: {type:"string"},
StockNumber:{type:"string"}
}
}
},
pageSize: 50
});
var binDropDownDataSource = [
{ BinNumber: "12345",PartNumber:"P-2929",StockNumber:"S-06565" },
{ BinNumber: "23456",PartNumber:"P-2323",StockNumber:"S-956565" },
{ BinNumber: "34567",PartNumber:"P-4344",StockNumber:"S-67676" } ];
function appendEditor (container, options) {
$('<input data-text-field="BinNumber" data-value-primitive="true" data-value-field="BinNumber" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList({
autoBind: false,
dataSource: binDropDownDataSource,
change:function(e){
var ddldataitem = this.dataItem();
var griditem = gridDS.at(0); // you might need to tweak this line
griditem.set("PartNumber",ddldataitem.PartNumber);
griditem.set("StockNumber",ddldataitem.StockNumber);
}
});
}
var grid= $("#bins").kendoGrid({
dataSource: gridDS,
scrollable: false,
autoBind:false,
batch:true,
editable : true,
navigatable: true,
toolbar: [ {name: 'custom-create', text: "Add New Line Item"}],
columns: [ {"field":"Row", title: "Row", width: "20px"},
{"field": "BinNumber","title":"Bin", editor: appendEditor},
{"field": "PartNumber", title: "Part ", width: "200px",editable: false },
{"field": "StockNumber", title: "Stock ", width: "200px",editable: false }
]
}).data("kendoGrid");
$(".k-grid-custom-create").on("click", function (e) {
gridDS.add({ Row:"1"});
});
The observable you had plugged in is not really necessary the underling data source is already observable, I have removed it. Please consider improving following line the index won't be always 0 var griditem = gridDS.at(0);
Here's how my DropDown is setup. This is a boolean field, so you will have to adjust it accordingly to your field
columns.Bound(m => m.IsInForecast).Title("Is Forecasted").ClientTemplate(
"# if (IsInForecast == true) { #" +
"<select id='#= OrderId #' onchange=save('#= OrderId #'); style='Width: 80px; color: 'navy' > " +
"<option id='yes' selected value='1'>Yes</option>" +
"<option id='no' value='0'>No</option>" +
"</select>" +
"# } else { #" +
"<select id='#= OrderId #' onchange=save('#= OrderId #'); style='Width: 80px; color: 'navy' > " +
"<option id='yes' value='1'>Yes</option>" +
"<option id='no' selected value='0'>No</option>" +
"# } #"
);
I want to reduce the height when a row is removed from ng-grid. I am able to delete a row reduce the grid height by a row. but grid footer is not moving from its position.
here is the code I am using
--html
<div class="gridStyle" ui-if="InterestInfo.length>0" ng-grid="gridOptions" ng- style="getTableStyle()" >
</div>
--javascript
var varFooterTempate = '<div><button type="button" class="btn btn-xs btn-success" ng-click="edit(row)" > ' +
' <span class="glyphicon glyphicon-plus"></span>' +
'</button>'
$scope.getTableStyle = function () {
var rowHeight = 35;
var headerHeight = 30;
var footerHeight = 30;
return {
height: ($scope.InterestInfo.length * rowHeight + headerHeight + footerHeight + 5) + "px"
};
};
$scope.gridOptions = {
data: 'InterestInfo',
headerRowHeight: 30,
rowHeight: 35,
footerRowHeight: 30,
showFooter: true,
footerTemplate: varFooterTempate,
columnDefs: [{ field: 'name', displayName: 'Name' },
{ field: 'type', displayName: 'Type' },
{ field: 'number', displayName: 'Number' },
{ field: '', displayName: 'Action', width: 140, sortable: false, cellTemplate: editableInPopup}],
multiSelect: false
};
$scope.removeRow = function () {
var index = this.row.rowIndex;
alert(index);
$scope.gridOptions.selectItem(index, false);
$scope.InterestInfo.splice(index, 1);
};
I believe that the documentation is currently wrong on this topic. Try setting gridFooterHeight instead of footerRowHeight in your gridOptions object.