KendoUI for AnfularJS Grid toolbar custom button swatch visibility - angularjs

I need to add custom buttons to a Kendo Grid toolbar and switch visibility of each other by clicking an another one (e.g. Button1 click hides Button1 and shows Button2, Button2 click hides Button2 and shows Button1).
I'm able to add these buttons but I can't change their visibility.
My code:
<div kendo-grid="grid" k-toolbar="toolbar" k-options="options">
</div>
class customGrid implements ng.IDirective {
public restrict = 'A';
public templateUrl = 'customGrid.directive.html';
public scope = {
options: '=',
grid: '='
};
constructor() {
}
public link = (scope) => {
scope.toolbarItems = [
{
name: 'play',
iconClass: 'fa fa-play',
handler: (toolbar: any) => {
//visibility switch here
}
},
{
name: 'pause',
iconClass: 'fa fa-pause',
handler: (toolbar: any) => {
//visibility switch here
}
}];
const toolbar: any[] = [];
for (let i = 0; i < scope.toolbarItems.length; i++) {
toolbar.push({
template: `<a ng-click="toolbarItems[${i}].handler()" class="k-button k-button-icontext" href="##"><i class="${scope.toolbarItems[i].iconClass}"></i> ${scope.toolbarItems[i].text}</a>`
});
}
scope.toolbar = toolbar;
}
I can manipulate directly to the DOM but maybe it is possible to do the same using angularJS?
Live Demo
P.S. This is just a sample, in real project "toolbarItems" is an directive's argument and their count can be different.

Updated dojo for the same. Instead of having separate button you can have one button and change/toggle their css class based on the need.
https://dojo.telerik.com/#amitdwivedi/ajeVoXUf
Hope this solves your purpose.
<!DOCTYPE html>
<html>
<head>
<base href="https://demos.telerik.com/kendo-ui/grid/angular">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="https://kendo.cdn.telerik.com/2015.3.930/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example" ng-app="KendoDemos">
<div ng-controller="MyCtrl">
<kendo-grid options="mainGridOptions" k-toolbar="toolbar">
</kendo-grid>
</div>
</div>
<script>
angular.module("KendoDemos", [ "kendo.directives" ])
.controller("MyCtrl", function($scope){
$scope.toolbarItems = [
{
name: 'pause',
iconClass: 'fa fa-play',
handler: ($event) => {
//visibility switch here
if(event.srcElement.className == 'fa fa-pause')
event.srcElement.className = "fa fa-play"
else
event.srcElement.className = "fa fa-pause"
}
}];
var toolbar = [];
for (var i = 0; i < $scope.toolbarItems.length; i++) {
toolbar.push({
template: `<a ng-click="toolbarItems[${i}].handler()" class="k-button k-button-icontext" href="##"><i class="${$scope.toolbarItems[i].iconClass}"></i></a>`
});
}
$scope.toolbar = toolbar;
$scope.mainGridOptions = {
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Employees"
}
},
sortable: true,
columns: [{
field: "FirstName",
title: "First Name",
width: "120px"
},{
field: "LastName",
title: "Last Name",
width: "120px"
},{
field: "Country",
width: "120px"
},{
field: "City",
width: "120px"
},{
field: "Title"
}]
};
})
</script>
</body>
</html>

Related

How to export kendo grid to excel with multi-lines in header cells

I want two(or more) lines of text in the header cell. I am aware about making the text wrap visually in the grid but I will not always have long text and besides, the wrapped text doesn't export in multi lines to the excel worksheet either. I want the line break to be at specific positions in the text both visually in the grid and in the exported excel worksheet.
For example, in the example I provided, I would like to be able to strip out the <br> html during export and have the export create a multi-line header.
So if I had the following kendo-grid heading:
I would like the excel export to look like this:
Instead <br> is outputted:
Plunker here http://plnkr.co/edit/v3TYgA?p=preview
Plunker code
<!DOCTYPE html>
<html>
<head>
<base href="http://demos.telerik.com/kendo-ui/grid/excel-export">
<title></title>
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.318/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.318/styles/kendo.material.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.318/styles/kendo.dataviz.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.318/styles/kendo.dataviz.material.min.css" />
<script src="http://cdn.kendostatic.com/2015.1.318/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2015.1.318/js/jszip.min.js"></script>
<script src="http://cdn.kendostatic.com/2015.1.318/js/kendo.all.min.js"></script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style>
html {
font-size: 12px;
font-family: Arial, Helvetica, sans-serif;
}
.k-grid-header .k-header {
white-space: normal !important;
}
</style>
</head>
<body>
<div id="example">
<div id="grid" style="width: 900px"></div>
<script>
$("#grid").kendoGrid({
toolbar: ["excel"],
excel: {
fileName: "Kendo UI Grid Export.xlsx",
proxyURL: "http://demos.telerik.com/kendo-ui/service/export",
filterable: true
},
excelExport: (e) => {
//let width for exported columns auto set
e.workbook.sheets[0].columns.forEach((col) => {
col.autoWidth = true;
});
},
dataSource: {
type: "odata",
transport: {
read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products"
},
schema: {
model: {
fields: {
UnitsInStock: {
type: "number"
},
ProductName: {
type: "string"
},
UnitPrice: {
type: "number"
},
UnitsOnOrder: {
type: "number"
},
UnitsInStock: {
type: "number"
}
}
}
},
pageSize: 7
},
sortable: true,
pageable: true,
columns: [ {
width: "35%",
field: "UnitPrice",
title: "Unit Price and some very loooong text that will make this line wrap. Not what I am looking for. Plus it doesn't export in multilines either.",
}, {
width: "30%",
field: "UnitsOnOrder",
title: "Units On Order"
}, {
width: "35%",
field: "UnitsInStock",
title: "Units In Stock <br> (Excludes foreign)"
}]
});
</script>
</div>
</body>
</html>
Perhaps you will have better results using a header template instead:
columns:[{
width: "35%",
field: "UnitsInStock",
title: "Units In Stock ",
headerTemplate: "Units In Stock <br> (Excludes foreign)"
}]
If you want "<br/>" tags to work/execute like HTML in Kendo Grid, you need to use "column.encoded" property.
Official Documentation : https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/configuration/columns.encoded
There's a DOJO link on the page as well, that sets a really good example.

Display the data from kendo-grid to html using angularjs

I am working on this . It displays the data using kendo - grid. However, what I need is when I click on a particular row in the table, all its content get fetched in an object and using that object I can display its fields below the table. How can I achieve that? Also, I believe we need to modify this code as well if we are using objects to display the fields. Any help would be appreciated.
First Name: {{FirstName}}<br>
Last Name: {{LastName}}<br>
Country: {{Country}}<br>
City: {{City}}<br>
It seems you need to listen for row selection (change event), and get the selected row, then bind it to angular variable inside your scope as describe in this update
The key here is the change event triggered upon selection/deselection
grid configs
...
change: function(e) {
var selection = this.select(),
selectedItem
;
if(selection && this.dataItem(selection)) {
$scope.selectedItem = this.dataItem(selection).toJSON();
} else {
$scope.selectedItem = {};
}
$scope.$apply();
}
...
grid configs
Two changes required in your code:
1) in HTML add on-change event handler function <kendo-grid options="mainGridOptions" k-on-change="handleChangeEvent(data, dataItem, columns)"> </kendo-grid>
2) in JavaScript
Set Kendo grid as selectable sortable: true
Define $scope.handleChangeEvent function
Code:
HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1411/styles/kendo.common.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1411/styles/kendo.default.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1411/styles/kendo.dataviz.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1411/styles/kendo.dataviz.default.min.css" />
<script src="http://cdn.kendostatic.com/2014.3.1411/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1411/js/angular.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1411/js/kendo.all.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div id="example" ng-app="KendoDemos">
<div ng-controller="MyCtrl">
<kendo-grid options="mainGridOptions" k-on-change="handleChangeEvent(data, dataItem, columns)"> </kendo-grid>
<h5>You selected: </h5>
First Name: {{FirstName}}<br>
Last Name: {{LastName}}<br>
Country: {{Country}}<br>
City: {{City}}<br>
</div>
</div>
</body>
</html>
And JavaScript:
angular.module("KendoDemos", ["kendo.directives"])
.controller("MyCtrl", function ($scope) {
$scope.handleChangeEvent = function(data, dataItem, columns) {
$scope.FirstName=dataItem.FirstName;
$scope.LastName=dataItem.LastName;
$scope.Country=dataItem.Country;
$scope.City = dataItem.City;
};
$scope.mainGridOptions = {
dataSource: {
type: "odata",
transport: {
read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Employees"
},
pageSize: 5,
serverPaging: true,
serverSorting: true
},
selectable: "row",
sortable: true,
pageable: true,
dataBound: function () {
this.expandRow(this.tbody.find("tr.k-master-row").first());
},
columns: [{
field: "FirstName",
title: "First Name",
width: "120px"
}, {
field: "LastName",
title: "Last Name",
width: "120px"
}, {
field: "Country",
width: "120px"
}, {
field: "City",
width: "120px"
}, {
field: "Title"
}]
};
});

kendo-ui grid inline edit angularjs

I want to have inline editing in my kendo-ui grid. Databinding seems to work fine but when I click the Update button after editing something the scope gets updated but the edit dialogs do not disappear. If a click on another edit button it gets into a defunct state. And after all it only does update the scope if I provide at least a dummy function as k-save. And for some reason clicking the Cancel button does update the scope. So the Cancel button does what I would expect from the Update button.
As you may see I want to update the local scope on client side and not send anything to any server.
Can somebody enlighten me about what is going wrong here?
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.common.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.default.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.dataviz.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.dataviz.default.min.css" />
</head>
<body>
<div id="example" ng-app="gridTestApp" ng-controller="TestController">
<kendo-grid
k-data-source="gridData"
k-columns="gridColumns"
k-on-change="selected = data"
k-selectable="true"
k-editable="editableOptions"
k-schema="gridSchema"
k-save="saveFunction">
</kendo-grid>
<p ng-show="selected">
<label>Artist: <input ng-model="selected.artist" /></label>
<br />
<label>Track: <input ng-model="selected.track" /></label>
</p>
<p>This is for testing data-binding</p>
<ul>
<li data-ng-repeat="gridRow in gridData">
<input ng-model="gridRow.artist"></input><input ng-model="gridRow.track"></input>
<br>
</li>
</ul>
<p>This is for testing data-binding</p>
<ul>
<li data-ng-repeat="gridRow in gridData">
<span ng-bind="gridRow.artist"></span> -<span ng-bind="gridRow.track"></span>
<br>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-1.11.2.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1119/js/kendo.all.min.js"></script>
<script>
angular.module("gridTestApp",[ "kendo.directives" ])
.controller("TestController", function($scope){
$scope.gridData = new kendo.data.ObservableArray([
{ artist: "Pink Floyd", track: "The dark side of the Moon" },
{ artist: "The Beatles", track: "I've just seen a face" },
{ artist: "Queen", track: "Innuendo" }
]);
$scope.gridColumns = [
{ field: "artist", title: "Artist" },
{ field: "track", title: "Track" },
{ command: /*"destroy"*/["edit", "destroy"], title: " ", width: "175px", editable: "inline" }
];
$scope.editableOptions = {mode: "inline", update: true, destroy: true};
$scope.gridSchema = {
model: {
id: "artist",
fields: {
artist: { type: "string", validation: { required: true } },
track: { type: "string", validation: { required: true } }
}
}
}
$scope.saveFunction = function(){
console.log("somehting was modified");
}
});
</script>
</body>
</html>
I have created a plnkr for you.
Your problem is the schema - this is not a grid configuration option but a DataSource configuration option.
I'd suggest creating an actual DataSource instead of an ObservableArray (using a string id might not be ideal either):
$scope.gridData = new kendo.data.DataSource({
data: [{
artist: "Pink Floyd",
track: "The dark side of the Moon"
}, {
artist: "The Beatles",
track: "I've just seen a face"
}, {
artist: "Queen",
track: "Innuendo"
}],
schema: {
model: {
id: "artist",
fields: {
artist: {
type: "string",
validation: {
required: true
}
},
track: {
type: "string",
validation: {
required: true
}
}
}
}
}
});
(demo)

AngularJS - dynamic rows and columns with a two way bound custom control

I am new to Angular and am stuck on my next step of development which is to have a custom control bound to a dynamic row-column table.
I have a simple fiddle here which shows how to data bind a custom control:
http://jsfiddle.net/paull3876/WPWAc/2/
And another fiddle here which is my starting point, shows how to bind a row-column table with data driven column names:
http://jsfiddle.net/paull3876/3mz5L/1/
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
function datacontroller($scope, $http)
{
$scope.mydata = [{f1:"r1f1", f2:"r1f2"}, {f1:"r2f1",f2:"r2f2"}, {f1:"r3f1",f2:"r3f2", f3:"Hello"}];
$scope.mycolumns = [{name:"Column 1", fieldname:"f1"}, {name:"Column 2", fieldname:"f2"}, {name:"Column 3", fieldname:"f3"}];
$scope.showdata = function()
{
alert(JSON.stringify($scope.mydata));
}
$scope.getcolumnname = function(cell)
{
return cell.fieldname;
}
}
</script>
</head>
<body>
<div data-ng-controller="datacontroller">
<table>
<tr>
<td data-ng-repeat="cell in mycolumns">{{cell.name}}</td>
</tr>
<tr data-ng-repeat="record in mydata">
<td data-ng-repeat="cell in mycolumns">
<input type="text" data-ng-init="mycol=getcolumnname(cell);" data-ng-model="record[mycol]" />
</td>
</tr>
</table>
<br />
<input type="button" value="Save Data" ng-click="showdata()" />
<br />
<br />
</div>
</body>
</html>
Now I want to take the second fiddle above, and replace the INPUT element with a user control which has two way data binding. I've spend a day on this already and can't get it working, so I guess I'm also needing some help on the concepts here
An explanation on top of a solution greatly appreciated.
http://jsfiddle.net/paull3876/rc7uC/1/
Here's the full working solution, I hope someone finds it useful.
<!DOCTYPE html>
<html >
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="-1">
<title>Angular</title>
<!--scr ipt src="htt ps://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js"></script>
</head>
<body>
<div data-ng-app="myApp" data-ng-controller="datacontroller">
<table>
<tr>
<td data-ng-repeat="cell in mycolumns">{{cell.name}}</td>
</tr>
<tr data-ng-repeat="record in mydata">
<td data-ng-repeat="cell in mycolumns">
<mycontrol data-my-model="record[cell.fieldname]"></mycontrol>
</td>
</tr>
</table>
<br />
<input type="button" value="Save Data" ng-click="showdata()" />
<input type="button" value="Change Divs" onclick="changediv()" />
<input type="button" value="Change Scope" onclick="changescope()" />
<br />
<br />
</div>
</body>
</html>
<script>
var globalscope;
var app = angular.module("myApp", [])
.directive("mycontrol", function ($compile) {
return {
restrict: "E",
scope: {
value: "=myModel"
},
template: "<div data-ng-bind='value'/>"
};
});
function datacontroller($scope, $http) {
globalscope = $scope;
var mydata = [];
// generate some data
for (var i = 0; i < 20; i++)
{
var row = {
f1:"f1x" + i,
f2:"f2x" + i,
f3:"f3x"+i,
f4:"f4x"+i,
f5:"f5x"+i,
f6:"f6x"+i,
f7:"f7x"+i,
f8:"f8x"+i,
f9:"f9x"+i,
f10:"f10x"+i,
f11:"f11x"+i,
f12:"f12x"+i,
f13:"f13x"+i
};
mydata.push(row);
}
// push it to angulars scope
$scope.mydata = mydata;
// generate some metadata for the columns
$scope.mycolumns = [{
name: "Column 1",
fieldname: "f1",
type: "input"
}, {
name: "Column 2",
fieldname: "f2",
type: "textarea"
}, {
name: "Column 3",
fieldname: "f3",
type: "div"
}, {
name: "Column 4",
fieldname: "f4",
type: "div"
}, {
name: "Column 5",
fieldname: "f5",
type: "div"
}, {
name: "Column 6",
fieldname: "f6",
type: "div"
}, {
name: "Column 7",
fieldname: "f7",
type: "div"
}, {
name: "Column 8",
fieldname: "f8",
type: "div"
}, {
name: "Column 9",
fieldname: "f9",
type: "div"
}, {
name: "Column 10",
fieldname: "f10",
type: "div"
}, {
name: "Column 11",
fieldname: "f11",
type: "div"
}, {
name: "Column 12",
fieldname: "f12",
type: "div"
}, {
name: "Column 13",
fieldname: "f13",
type: "div"
}];
$scope.showdata = function () {
alert(JSON.stringify($scope.mydata));
};
$scope.getcolumnname = function (cell) {
return cell.fieldname;
};
}
function changediv()
{
// this will change the data in the divs but it won't reflect back to the scope
var divs = document.getElementsByClassName("fred");
for (var i = 0; i < divs.length; i++)
{
var div = divs[i];
div.innerText = "XXXX";
}
}
function changescope()
{
// shows how to change data programmatically and have it reflected in the controls and in the scope data
var scope = globalscope;
for (r in scope.mydata)
{
scope.mydata[r].f3 = "UUUU";
}
scope.$apply();
}
</script>

Updating Shield UI Chart with values from textboxes on the page

I am using a Shield UI Chart on a page where users can enter 3 values which are than showed on the chart. I have a button which triggers the event. Here is my code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://www.shieldui.com/shared/components/latest/chart/css/shield-chart.min.css">
<script type="text/javascript" src="http://www.shieldui.com/shared/components/latest/chart/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="http://www.shieldui.com/shared/components/latest/chart/js/shield-chart.all.min.js"></script>
<script>
function myFunction()
{
var containter = $("#chart").swidget();
var info = new Array();
info[0]=parseFloat(document.getElementById("a").value);
info[1]=parseFloat(document.getElementById("b").value);
info[2]=parseFloat(document.getElementById("c").value);
containter.destroy();
$("#chart").shieldChart(
{
seriesSettings: {
line: {
applyAnimation: {
duration: 0
},
pointMark: {
enabled: false
}
}
},
tooltipSettings: {
enabled: false
},
exportOptions:
{
image: false,
print: false
},
axisX: {
min: 0,
max: 5
},
primaryHeader: {
text: "Chart"
},
dataSeries: [
{
seriesType: 'bar',
collectionAlias: 'chart',
data: [info[0],info[1],info[2]]
}
]
}
);
}
</script>
</head>
<body>
<button onclick="myFunction()">Refresh Chart</button>
<table>
<tr>
<td>
<div id="chart" style="width: 300px; height: 300px; margin: auto;"></div>
</td>
</tr>
</table>
<p id="demo"></p>
<input type=text id="a" value='123'>Value A</input>
<input type=text id="b" value='23'>Value B</input>
<input type=text id="c" value='3'>Value C</input>
</body>
</html>
However there is some error that prevents the values from being displayed. Actually the whole chart won’t show. Where might be my mistake?
The is one error that you are making which can be resolved in 2 ways:
1. You can remove the
containter.destroy();
statement. So You will not recreate the existing chart, but create a new one each time the button is pressed.
You could keep the above mentioned statement, but you need to place this code
$(document).ready(function () {
var info = new Array();
info[0]=parseFloat(document.getElementById("a").value);
info[1]=parseFloat(document.getElementById("b").value);
info[2]=parseFloat(document.getElementById("c").value);
$("#chart").shieldChart({
exportOptions:
{
image: false,
print: false
},
tooltipSettings: {
enabled: false
},
seriesSettings: {
line: {
applyAnimation: {
duration: 0
},
pointMark: {
enabled: false
}
}
},
axisX: {
min: 0,
max: 5
},
primaryHeader: {
text: "Chart"
},
dataSeries: [
{
seriesType: 'bar',
collectionAlias: 'Chart',
data: [info[0],info[1],info[2]]
}
]
});
});
so you will already have one chart which to destroy and recreate and you will be able to show the data from the first time page is loaded.

Resources