Add a checkbox column in Handsontable - checkbox

Have you ever make a checkbox column in Handsontable?
I try to use every way to do it, but it's not working.
When user click checkbox on header, all row in column was be checked.
Thanks for any help.

You can create a checkbox column by simply setting the column type option to 'checkbox'.
var $container = $("#example1");
$container.handsontable({
data: data,
startRows: 5,
colHeaders: true,
minSpareRows: 1,
columns: [
{data: "id", type: 'text'},
//'text' is default, you don't actually have to declare it
{data: "isActive", type: 'checkbox'},
{data: "date", type: 'date'},
{data: "color",
type: 'autocomplete',
source: ["yellow", "red", "orange", "green", "blue", "gray", "black", "white"]
}
]
});
For more detail see this example

HTML:
<div id="example2" class="handsontable"></div>
Javascript:
var myData = [{
name: "Marcin",
active: true
}, {
name: "Jude",
active: false
}, {
name: "Zylbert",
active: false
}, {
name: "Henry",
active: false
}]
var $container = $("#example2");
$container.handsontable({
data: myData,
rowHeaders: true,
columns: [{
data: 'name'
}, {
type: 'checkbox',
data: 'active'
}],
colHeaders: function (col) {
switch (col) {
case 0:
return "<b>Bold</b> and <em>Beautiful</em>";
case 1:
var txt = "<input type='checkbox' class='checker' ";
txt += isChecked() ? 'checked="checked"' : '';
txt += "> Select all";
return txt;
}
}
});
$container.on('mouseup', 'input.checker', function (event) {
var current = !$('input.checker').is(':checked'); //returns boolean
for (var i = 0, ilen = myData.length; i < ilen; i++) {
myData[i].active = current;
}
$container.handsontable('render');
});
function isChecked() {
for (var i = 0, ilen = myData.length; i < ilen; i++) {
if (!myData[i].active) {
return false;
}
}
return true;
}
Here's the example you're looking for
http://jsfiddle.net/yr2up2w5/
Hope this helps you.

There's now a checkbox tutorial in the Handsontable documentation.

Related

How can I generate a custom legend in chart.js in React [duplicate]

I need the value of chart show after name of data for example ([colour of data] Car 50, [colour of data] Motorcycle 200). I've tried change the value of legend title but it doesn't work at all
Here is it my code:
var ctx = document.getElementById('top-five').getContext('2d');
var myChartpie = new Chart(ctx, {
type: 'pie',
data: {
labels: {!! $top->pluck('name') !!},
datasets: [{
label: 'Statistics',
data: {!! $top->pluck('m_count') !!},
backgroundColor: {!! $top->pluck('colour') !!},
borderColor: {!! $top->pluck('colour') !!},
}]
},
options: {
plugins: {
legend: {
display: true,
title: {
text: function(context) {//I've tried to override this but doesn't work
var value = context.dataset.data[context.dataIndex];
var label = context.label[context.dataIndex];
return label + ' ' + value;
},
}
},
},
responsive: true,
}
});
You can use a custom generateLabels function for this:
var options = {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
}]
},
options: {
plugins: {
legend: {
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
return datasets[0].data.map((data, i) => ({
text: `${chart.data.labels[i]} ${data}`,
fillStyle: datasets[0].backgroundColor[i],
index: i
}))
}
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>
The below is a direct over ride of the default label generation found in the controller here. I have made one change on the text property within the generateLabels function in order to append the data value. It preserves the data toggling and strikethrough styling when a label is toggled.
plugins: {
legend: {
labels: {
generateLabels(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
const {labels: {pointStyle}} = chart.legend.options;
return data.labels.map((label, i) => {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: `${label}: ${data['datasets'][0].data[i]}`,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
pointStyle: pointStyle,
hidden: !chart.getDataVisibility(i),
// Extra data used for toggling the correct item
index: i
};
});
}
return [];
}
},
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
}
//...
}
[1]: https://github.com/chartjs/Chart.js/blob/master/docs/samples/legend/html.md
You can also use the base implementation to reduce the amount of copied code. Note that some chart types (like donut) already overrides the default label generation.
plugins: {
legend: {
labels: {
generateLabels: function (chart) {
return Chart.defaults.plugins.legend.labels.generateLabels(chart).map(function (label) {
var dataset = chart.data.datasets[label.datasetIndex];
var total = 0;
for (var j = 0; j < dataset.data.length; j++)
total += dataset.data[j].y;
label.text = dataset.label + ': ' + total;
return label;
});
}
}
}
}

Change React MUI DataTable Row Color onRowClick()

I am trying to change the background color or text color of a row after it is clicked using MUI DataTables. Does anyone know how I could go about doing this? I tried playing around with onRowClick but I can not figure out a way to update the color of a specific row. Thank you so much!
export default function CoursesTable() {
const columns = [
{
name: "dept",
label: "Dept",
options: {
filter: false,
sort: false,
}
},
{
name: "number",
label: "ID",
options: {
filter: false,
sort: true,
}
},
{
name: "title",
label: "Name",
options: {
filter: false,
sort: false,
}
},
{
name: "prereqs",
label: "Prerequisites",
options: {
filter: false,
sort: false,
display: false,
}
},
{
name: "description",
label: "Description",
options: {
filter: false,
sort: false,
display: false,
}
}
];
const data = courses;
var arr: string[] = [];
const handleRowClick = (rowData, rowMeta) => {
const courseID = rowData[0] + ' ' + rowData[1];
if (arr.includes(courseID)){
const index = arr.indexOf(courseID);
arr.splice(index, 1);
}
else if (arr.length >= 7) {
alert('You can not have more than 7 courses in your cart!')
}
else {
arr.push(courseID);
}
};
return (
<div>
<MUIDataTable
title = {"Course List"}
data = {data}
columns = {columns}
options={{
selectableRowsHideCheckboxes: true,
caseSensitive: false,
download: false,
onRowClick: handleRowClick
}}
/>
<Cart arr = {arr}/>
</div>
)
}
Please let me know if you need any further clarifications of what I am trying to do!

How to drilldown to third level when its data is determined by second's click event?

So, I have been trying to use drill down to multiple levels, problem I am facing is that I couldn't drill down to the third level because the data will be fetched by ajax upon second drilldown's selection.
for example, refer to this link:
https://codepen.io/ajaymalhotra15/pen/aZpxXq
drilldown example
Here, the third level is possible because he has the data already, but mine will be depended on seconds selection.
So, how to make this happen, where am I supposed to call the ajax request and set the drill down series data dynamically?
EDIT:
Highcharts.chart("energy_chart", {
chart: {
type: "column",
spacingBottom: 15,
spacingTop: 10,
spacingLeft: 10,
spacingRight: 10,
backgroundColor: "#f2f2f2",
events: {
load: function() {
var fin = new Date();
var finDate = fin.getDate();
var finMonth = fin.getMonth();
var finYear = fin.getFullYear();
var ini = new Date();
ini.setFullYear(ini.getFullYear() - 1);
var iniDate = ini.getDate();
var iniMonth = ini.getMonth();
var iniYear = ini.getFullYear();
if (this.yAxis[0].dataMax == 0) {
this.yAxis[0].setExtremes(null, 1);
}
//this.yAxis.set
this.xAxis[0].setExtremes(
Date.UTC(iniYear, iniMonth, iniDate),
Date.UTC(finYear, finMonth, finDate)
);
},
drilldown: function(e) {
var charts_this = this;
var inidrillDate = new Date(e.point.x);
setTimeout(function() {
inidrillDate.setDate(0);
inidrillDate.setMonth(inidrillDate.getMonth());
var DateinidrillDate = inidrillDate.getDate();
var MonthinidrillDate = inidrillDate.getMonth();
var YearinidrillDate = inidrillDate.getFullYear();
var findrillDate = inidrillDate;
findrillDate.setMonth(findrillDate.getMonth() + 1);
findrillDate.setDate(findrillDate.getDate() - 1);
var DatefindrillDate = findrillDate.getDate();
var MonthfindrillDate = findrillDate.getMonth();
var YearfindrillDate = findrillDate.getFullYear();
charts_this.xAxis[0].setExtremes(
Date.UTC(
YearinidrillDate,
MonthinidrillDate,
DateinidrillDate
),
Date.UTC(
YearfindrillDate,
MonthfindrillDate,
DatefindrillDate
)
);
if (charts_this.yAxis[0].dataMax === 0) {
charts_this.yAxis[0].setExtremes(null, 1);
}
}, 0);
}
}
},
title: {
text: '<p className="energy_gen">Energy Generated</p>'
},
exporting: { enabled: false },
xAxis: {
type: "datetime",
labels: {
step: 1
},
dateTimeLabelFormats: {
day: "%e"
}
},
yAxis: {
title: {
text: "kWh"
}
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: "pointer",
dataLabels: {
enabled: true,
format: "{point.y}"
},
color: "#fcd562",
point:{
events:{
click:function(event){
if(this.options!=null){
var dayOfYear=new Date(this.x).getFullYear() +"-"+(new Date(this.x).getMonth()+1)+"-"+new Date(this.x).getDate();
var formatted_date = new Date(this.x).getDate() + " " + months[(new Date(this.x).getMonth())] +" "+ new Date(this.x).getFullYear();
// document.getElementById('chart_date_id').innerHTML = formatted_date; //setting modal title with current date
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
var sync_charts = $('.chart');
for (i = 0; i < sync_charts.length; i = i + 1) {
var chart_1 = sync_charts[i];
var chart_2 = chart_1.getAttribute('data-highcharts-chart');
chart=Highcharts.charts[chart_2];
event = chart.pointer.normalize(e.originalEvent);
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
});
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
Highcharts.Point.prototype.highlight = function (event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(
e.min,
e.max,
undefined,
false,
{ trigger: 'syncExtremes' }
);
}
}
});
}
}
axios({
url: config.fvcstat,
method: "POST",
data: {
"customerId":self.props.location.state.detail.customerId,"rmsVendorId":self.props.location.state.detail.rmsVendorId,
"date":dayOfYear,
"powerType":self.props.location.state.detail.powerType
},
headers: {
"Content-Type": "application/json"
}
}).then((res)=>{
let activity = fvc.data;
if($('.chart')){
$('.chart').remove();
}
$.each(activity.datasets, function (i, dataset) {
console.log(1)
var chartDiv = document.createElement('div');
chartDiv.className = 'chart';
document.getElementById('container').appendChild(chartDiv);
Highcharts.chart(chartDiv,{
chart: {
},
plotOptions: {
series: {
marker:{
enabled:false
}
}
},
exporting: { enabled: false },
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair:{ width: 3},
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value}'
},categories: activity.xData
},
yAxis: {
title: {
text: null
}
},
series: [{
data: dataset
}],
tooltip: {
positioner: function () {
return {
x: this.chart.chartWidth - this.label.width,
y: 10 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
})
}
}
}
}
}
},
tooltip: {
formatter: function() {
if (this.point.options.drilldown) {
return (
"Energy generated: <b> " +
this.y +
"</b> kWh " +
"<br>" +
Highcharts.dateFormat("%b %Y", new Date(this.x))
);
} else {
return (
"Energy generated: <b> " +
this.y +
"</b> kWh " +
"<br>" +
Highcharts.dateFormat("%e %b %Y", new Date(this.x))
);
}
}
},
series: [{'data':obj.data,'name':obj.name,"color":"#4848d3"}],
drilldown: {
series: obj.data
}
});
So, here if you notice in plotoptions i am trying to create a whole new chart which is a synced line charts showing frquency, voltage and current.
But, i am guessing my approach is not correct as i am plotting a new highchart.
So, how do i make this synced line chart part of my drilldown.
let me know if you require any help in understanding.
I will suggest first minimize the plotoption. Then expand for further fuck up :P
Thanks.
You can put all your logic to get the third level data and to create a drilldown series in drilldown event:
chart: {
type: 'column',
events: {
drilldown: function(e) {
if (!thirdLevel.length) {
// get data
}
if (!e.seriesOptions) {
var chart = this,
drilldowns = {
'Animals': {
name: 'Animals',
data: [
['Cows', 2],
['Sheep', 3]
]
},
'Fruits': {
name: 'Fruits',
data: [
['Apples', 5],
['Oranges', 7],
['Bananas', 2]
]
},
'Cars': {
name: 'Cars',
data: [
['Toyota', 1],
['Volkswagen', 2],
['Opel', 5]
]
}
},
series = drilldowns[e.point.name];
chart.addSingleSeriesAsDrilldown(e.point, series);
chart.applyDrilldown();
}
}
}
}
Live demo : http://jsfiddle.net/BlackLabel/86v3L4ft/
API Reference: https://api.highcharts.com/highcharts/chart.events.drilldown

Kendo-ui grid filtering

I am trying to filter items in a grid by tags, the data in the grid looks like this
[
{ id: 0, tags: [{ text: 'boat' }, { text: 'summer' }] },
{ id: 1, tags: [{ text: 'boat' }] },
{ id: 2, tags: [{ text: 'travel' }] },
{ id: 3, tags: [{ text: 'boat' }] },
{ id: 4, tags: [{ text: 'travel' }] },
{ id: 5, tags: [{ text: 'travel' }, { text: 'summer' }] }
]
And the function for filtering looks like this
$scope.filterGrid = function (e) {
var grid = $('#imageGrid').data('kendoGrid');
var val = [{ text: 'travel' }, { text: 'summer' }];
grid.dataSource.filter({});
if ($.trim(val) !== '') {
grid.dataSource.filter({
logic: 'or',
filters: [{
field: 'tags',
operator: function (item) {
var status = false;
for (var n = 0, length2 = val.length; n < length2; n++) {
for (var i = 0, length = item.length; i < length; i++) {
if (item[i].text.indexOf(val[n].text) !== -1) {
status = true;
break;
}
}
}
return status;
}
}]
});
}
};
With this example where val = travel, summer i would like to only show the items with both tags (id 5) but it shows all items containing either of the tags (id: 0,2,4,5)
What am i doing wrong and is there a better way to do this with kendo?
Your filter algorithm was accepting the item to have at least one of the two desired values, because the loop break when find one here:
if (item[i].text.indexOf(val[n].text) !== -1) {
status = true;
break;
}
I have changed a little your code to this:
operator: function (item) {
var found = 0;
for (var i = 0, length = item.length; i < length; i++) {
for (var n = 0, length2 = val.length; n < length2; n++) {
if (item[i].text.indexOf(val[n].text) !== -1) {
found++;
break;
}
}
}
return found == val.length;
}
It counts the total of found tags(found) and return true only if the number of found items is the same as the search items(val.length). So it starts iterating through item, and not through val, as the rule stands for the item has to be all the values, and not the way around. So for each item is performed a check if it has all val items and sum found counter. At the end, if found is equal val.length it means that all items on val are inside item.
Working demo

Retrieving tree node text in KendoUI/Angular

The objective of this plunk is to query a specific tree node (given its id stored in the variable sk) and show an alert with its text. Enter a number in the input field (the node sk value), click on the button and you should see an alert with the node text.
The get method and hasChildren in the hierarchical data source are not working, any ideas?
HTML:
<div kendo-tree-view k-data-source="treeData"></div>
<br/><br/>
<button ng-click="queryTree()">Get Text</button>
<input ng-model="sk">
Javascript:
function MyCtrl($scope) {
$scope.sk = 3;
$scope.treeData = new kendo.data.HierarchicalDataSource({
data: [
{ sk: 11, text: "Furniture", expanded:true, items: [
{ sk: 2, text: "Tables & Chairs"},
{ sk: 3, text: "Sofas" },
{ sk: 4, text: "Occasional Furniture" }
] },
{ sk: 12, text: "Decor", expanded:true, items: [
{ sk: 6, text: "Bed Linen" },
{ sk: 7, text: "Curtains & Blinds" },
{ sk: 8, text: "Carpets" }
] }
],
schema: {
model: {
id: "sk",
hasChildren: function(item) {
return item.sk > 10;
}
}
}
});
$scope.queryTree = function(){
$scope.treeData.fetch(function() {
var dataItem = $scope.treeData.get($scope.sk);
alert(dataItem.text);
});
};
}
You should access the datasource directly:
$scope.queryTree = function(){
var nodeDataItem = $scope.treeData.get($scope.sk);
alert(nodeDataItem.text)
};
Here is a working plunkr for you. http://plnkr.co/edit/N4FYVh227HjvYOoWMYo4

Resources