Custom legend labels in my rechart chart - recharts

I have a pretty straight forward data array for my recharts component :
{name: '12.1.2011', series1: 4000, series2: 2400, series3: 2400},
{name: '12.2.2011', series1: 3000, series2: 1398, series3: 2210},
{name: '12.3.2011', series1: 2000, series2: 9800, series3: 2290}
I would like to have labels for the series values in my Legend. Instead of the chart showing me the different colors for "series1", "series2", and "series3".
Of course I could set the actual values I want to use for my legend in the JSON already but this just doesn't look right. Eg :
{name: '12.1.2011', 'My nice long descriptive text': 4000, 'Some other text': 2400, 'Some other descriptive text': 2400},
{name: '12.2.2011', 'My nice long descriptive text': 3000, 'Some other text': 1398, 'Some other descriptive text: 2210},
{name: '12.3.2011', 'My nice long descriptive text': 2000, 'Some other text': 9800, 'Some other descriptive text: 2290}
I need to map my series level to a descriptive label.
I have looked at content in Legend : http://recharts.org/#/en-US/api/Legend, but that seems more concerned with completely rewriting the Legend Component.

In your Line, Bar and Area add a name attribute.
Example:
<Line name="# Apples" type="monotone" dataKey="series1" stroke="#FF0000" />
<Line name="# Bananas" type="monotone" dataKey="series2" stroke="#FFFF00" />
<Line name="# Grapes" type="monotone" dataKey="series3" stroke="#FF00FF" />
The legend will pick this up automatically:
http://recharts.org/en-US/api/Legend
By default, the content of legend is generated by the name of Line,
Bar, Area, etc. When no name has been setted, dataKey will be used to
generate legend content alternatively.

If you're looking to get this working on a <Pie /> you can override the <Legend /> payload. Please see the following example;
<Legend
payload={
data.map(
(item, index) => ({
id: item.name,
type: "square",
value: `${item.name} (${item.value}%)`,
color: colors[index % colors.length]
})
)
}
/>
http://recharts.org/en-US/api/Legend#payload

For custom legend, use content props, Ref: https://recharts.org/en-US/api/Legend#content
const renderLegend = (props) => {
const { payload } = props;
return (
<ul>
{
payload.map((entry, index) => (
<li key={`item-${index}`}>{entry.value}</li>
))
}
</ul>
);
}
<Legend content={renderLegend} />

Related

How to style a data table td in Vuetify?

Good Afternoon.
I'm trying to build a stylized table with "v-data-table", without being used to it. Mainly put style into second or third cell (table, tr, td). I don't find the solution for my problem. Help me, please.
thanks.
You can use the item-class attributes to style every row
Property on supplied items that contains item’s row class or function that takes an item as an argument and returns the class of corresponding row
It works as the following :
It takes a function as argument that return a class depending on the row.
If you want to return a specific class depending on the item use it like this :
<template>
<v-datad-table :item="items" :item-class="getMyClass"></v-data-table>
</template>
<script>
methods: {
getMyClass(item){
// here define your logic
if (item.value === 1) return "myFirstClass"
else return "mySecondClass"
}
}
</script>
If you want to always give the same class you can just return the class you want to give (note that this is the same as stylized the td of the table using css)
<template>
<v-data-table :items="items" :item-class="() => 'myClass'"></v-data-table>
</template>
In your case, you can add an index to your data using a computed property and added a class based on the index
computed: {
myItemsWithIndex(){
retunr this.items.map((x, index) => {...x, index: index})
}
}
methods: {
getMyClass(item){
if(item.index === 2 || item.index === 3) return "myClass"
}
}
Working example
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => {
return {
items: [
{name: "foo"},
{name: "bar"},
{name: "baz"},
{name: "qux"},
{name: "quux"},
{name: "corge"},
{name: "grault"},
],
headers: [{ text: 'Name', value: 'name'}],
}
},
computed: {
itemsWithIndex(){
return this.items.map((item, index) => ({ ...item, index:index }))
}
},
methods: {
getMyClass(item){
if(item.index === 2 || item.index === 3){
return "myClass"
} else return
}
}
})
.myClass {
background: red
}
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.4/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.4/dist/vuetify.min.css" />
<div id="app" data-app>
<v-data-table :items="itemsWithIndex" :headers="headers" :item-class="getMyClass"></v-data-table>
</div>
I'd bet that what you're trying to achieve can be done using named slots
See this example from the docs. Basically, the template tag you see in the example will become whatever node is 'above it' (which it really isn't because it takes its place, but you get the point). For instance, in the case of data-tables, <template #item="{ item }">... represents every <td> of your table. Then you can use the destructured item and apply some logic to it to still of modify you table as you will.
Don't forget to upvote/validate the answer if it helped your to solve your issue, comment if you need more details and welcome to Stack!
There are also the possibility to use cellClass, which is part of the headers.
The image is from https://vuetifyjs.com/en/api/v-data-table/#props
As computed property i have:
headers() {
return [
{ text: this.$t('Name'), align: 'left', sortable: true, value: 'name', cellClass:'select' },
{ text: 'CVR', sortable: false, value: 'cvrno' },
{ text: this.$t('Updated At'), sortable: false, value: 'updatedAt' }
]
},
and by v-data-table tag looks like:
<v-data-table
v-model="selected"
:headers="headers"
:items="customerFiltered"
:loading="loadingCustomers"
:items-per-page="-1"
selected-key="id"
show-select
hide-default-footer
fixed-header
>

Is there a way to create a custom plugin for CK Editor to support inline SVGs?

I want to create a plugin that lets users insert a widget with a SVG icon and some text. I created the widget that allows the user to add text but when I try to add an SVG it striped all of my attributes out. Is there a way to allow inline SVGs inside of the editor. I can not find any documentation on SVG support.
schema.register('actionIcon', {
allowWhere: '$text',
isInline: true
allowAttributes: ['name', 'class']
})
schema.register('actionCircle', {
allowWhere: '$text',
isInline: true,
allowAttributes: ['name', 'class', 'cx', 'cy', 'r', 'stroke', 'fill']
})
// ...
conversion.elementToElement({
model: 'actionIcon',
view: {
name: 'svg',
classes: 'action-icon'
}
})
conversion.elementToElement({
model: 'actionCircle',
view: {
name: 'circle',
classes: 'action-circle',
['cx']: '50',
['cy']: '50',
['r']: '40',
['stroke']: 'green',
['fill']: 'yellow'
}
})
Result:
<p>
<svg class="action-icon">
<circle class="action-circle"> </circle>
</svg>
<span class="placeholder ck-widget" contenteditable="false">
Item
</span>
</p>
I expected to create a scheme and converter for an svg and insert that into the widget but ck editor strips away all the attributes I verbosely defined.

Recharts - Tooltip for each Bar in a Bar Chart composed of three bars

I have in my bar chart three different bars.
I would like to have a tooltip for each bar in the bar chart and not just one for the three.
import React from 'react';
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
} from 'Recharts';
const data = [
{ name: 'Page A', uv: 4000, pv: 1982, amt: 2400 },
{ name: 'Page B', uv: 3000, pv: 1398, amt: 4739 },
{ name: 'Page C', uv: 2000, pv: 9800, amt: 9056 },
{ name: 'Page D', uv: 2780, pv: 3908, amt: 2000 },
{ name: 'Page E', uv: 1890, pv: 4678, amt: 2181 },
{ name: 'Page F', uv: 2390, pv: 3800, amt: 2873 },
{ name: 'Page G', uv: 3490, pv: 1987, amt: 2100 },
];
class SimpleBarChart extends React.Component {
render() {
return (
<BarChart
width={600}
height={300}
data={data}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="pv" barSize={20} fill="#8884d8" />
<Bar dataKey="amt" barSize={20} fill="#82ca9d" />
<Bar dataKey="uv" barSize={20} fill="#ffc658" />
</BarChart>
);
}
}
export default SimpleBarChart;
Following Natasha's answer, first create a custom tooltip:
<Tooltip content={<CustomTooltip/>} />
Add a function/component to render the custom contents. The variable tooltip is used to identify which Bar is being hovered over. The contents can be customized using the payload which contains all the bars in the selection.
var tooltip
const CustomTooltip = ({ active, payload }) => {
if (!active || !tooltip) return null
for (const bar of payload)
if (bar.dataKey === tooltip)
return <div>{ bar.name }<br/>{ bar.value.toFixed(2) }</div>
return null
}
Finally, add name and onMouseOver props to each <Bar> element:
<Bar dataKey="pv" barSize={20} fill="#8884d8"
name="Name" onMouseOver={ () => tooltip="pv" } />
When the mouse hovers over that <Bar> it will set the tooltip variable to the value "pv". Then the CustomTooltip will find that entry in the payload parameter and display the name and value.
You can create a custom tooltip like in the example here:
http://recharts.org/en-US/examples/CustomContentOfTooltip <---- Customized tooltip example (from recharts documentation)
After you create a customized tooltip, you can call it in the Bar component's OnMouseOver property which is in the documentation here:
http://recharts.org/en-US/api/Bar#onMouseOver <---- OnMouseOver
You could also use OnMouseEnter and OnMouseLeave but I know that doesn't work for everyone.
You might want to create a function that shows the tooltip when the mouse hovers over a bar and hides the tooltip when the mouse stops hovering over the bar.
You can add shared={false} props into Tooltip like this:
<Tooltip shared={false} />

C3 / D3 bar chart with horizontal scroll

I'm working on creating a c3 bar chart where each bar represents the # of people who joined a program in the given week. Data is just an array of objects with [{week, # of people}, {week, # of people}, etc.]
Ideally, I want the latest 6 weeks to show in the chart, but I want to be able to scroll horizontally to see past weeks.
I saw one answer to this (D3.js scrolling bar chart), but in this case, the axis did not stay visible when scrolling - which I would like to do.
Any help would be much appreciated.
c3.js allows you to make a "Sub Chart", which in essence is similar to a stock chart such as those you would see on Google Finance.
I suspect you would be better off letting the Sub Chart be your mechanism for scrolling than trying to implement a scrollbar from css.
One of the nice features of the c3 Sub Chart is how it allows to set the 'default extent' for the Sub Chart. What you could do is use the extent to default to a limited number of weeks, and from there, the user can manipulate the Sub Chart slider/brush as they see fit. Here is a simple implementation/dummy example:
axis.x.extent
http://c3js.org/reference.html
...Set default extent for subchart and zoom.
c3 Sub Chart
http://c3js.org/samples/options_subchart.html
working example in jsfiddle
http://jsfiddle.net/y6tns4mt/1/
HTML
<div class="container">
<div class="row">
<div class="col-md-12">
<p>My Chart Title</p>
<div>
<div id="my-chart"></div>
</div>
</div>
</div>
</div>
JavaScript for c3 chart
var chart = c3.generate({
bindto: '#my-chart',
data: {
columns: [
['people', 30, 200, 100, 400, 150, 250, 40, 50, 70, 80, 90, 100, 17, 47, 51, 141]
],
type: 'bar'
},
subchart: {
show: true
},
axis: {
x: {
extent: [13, 16]
}
},
tooltip: {
format: {
title: function (d) {
return 'Week ' + d;
}
}
}
});

Data and button in same column kendo grid

I am working on HTML5 and javascript.
Is it possible to add data and button in the same column in kendo grid.
Need help.
Also in view page, you can use ClientTemplate to achieve this:
#(Html.Kendo().Grid<ViewModel>().Name("grid")
.DataSource(src => src.Ajax().PageSize(10).Read(read => read.Action("Action", "Controller"))
.Columns(col =>
{
col.Bound(e => e.Name).ClientTemplate("<input type='button' value='CLICK' onclick='XYZ();'><label>#= (Name== null) ? ' ' : Name #</label>");
})
.Selectable()
.Scrollable()
)
Yes, it is! Simply use a template for it. Example:
Define the following template:
<script id="template" type="kendoui/template">
<button class="ob-click-me k-button">Click me</button>
<span>#= LastName #</span>
</script>
and the grid as:
var grid = $("#grid").kendoGrid({
dataSource: ds,
...
columns :
[
{ field: "FirstName", width: 90, title: "First Name" },
{
field: "LastName",
width: 200,
title: "Last Name",
template: $("#template").html()
}
]
}).data("kendoGrid");
You can see a running example even defining a handler for the button here: http://jsfiddle.net/OnaBai/qe3tf4tx/

Resources