I am trying to change the chart theme dynamically using this code:
changeTheme(e) {
this.previewService.chartConfig.theme = this.themes[e.target.attributes.value.value];
}
This is the way I am changing the theme dynamically, it got reflected in json source of chart but it is not updating the actual theme.
Could you show me a working example for same?
Please check this fiddle.
https://jsfiddle.net/pshiral/30955m70/7/
Full disclosure, I'm a member of the ZingChart team.
Themes work at the highest level in our library. We build pieces of the chart based on attributes in the theme working our way in a top to bottom fashion. Because of this, you can only set and update a theme at the render level. This means you will have to destroy your chart and re-render it to changes themes. Check out the following:
var myConfig = {
type: "bar",
series : [
{
values : [35,42,67,89,25,34,67,85]
}
]
};
zingchart.render({
id : 'myChart',
data : myConfig,
height: 400,
width: 600
});
function changeTheme(e) {
zingchart.exec('myChart','destroy');
zingchart.render({
id : 'myChart',
data : myConfig,
height : 400,
width : 600,
theme: this.id
});
}
document.getElementById('light').addEventListener('click',changeTheme);
document.getElementById('dark').addEventListener('click',changeTheme);
<!DOCTYPE html>
<html>
<head>
<script src= "https://cdn.zingchart.com/zingchart.min.js"></script>
<script> zingchart.MODULESDIR = "https://cdn.zingchart.com/modules/";</script>
</head>
<body>
<div id='myChart'></div>
<button id='light'>Light Theme</button>
<button id='dark'>Dark Theme</button>
</body>
</html>
Full disclosure, I'm a member of the ZingChart team.
I have updated our Angular Directive to watch for changes on the zcRender object. It will take care of chart cleanup and re-rendering the chart for you. The latest version 1.2.1 can be downloaded from github or npm. I put together a small demo in a plnkr demonstrating the changes.
// If defaults or theme has changed.
// Destroy and re-render chart
$scope.$watch('zcRender', function(newValue, oldValue, scope) {
if(initializing.render){
initializing.render = !initializing.render;
return;
}
// console.log('---newValue',newValue)
// console.log('---oldValue',oldValue)
// console.log('---scope',scope)
zingchart.exec(scope.id, 'destroy');
scope.zcRender = newValue;
scope.renderChart();
},true);
// Break render function out of link so we can consistently
// call the same rendering algorithm
$scope.renderChart = function (){
var id = $element.attr('id');
//Defaults
var _json = {
data : {
type : 'line',
series : []
},
width : 600,
height: 400
};
//Add render object.
if($scope.zcRender){
mergeObject($scope.zcRender, _json);
}
//Add JSON object
if($scope.zcJson){
mergeObject($scope.zcJson, _json.data);
}
//Add Values
if($scope.zcValues){
injectValues($scope.zcValues, _json.data);
}
//Add other properties
_json.data.type = ($attrs.zcType) ? $attrs.zcType : _json.data.type;
_json.height = ($attrs.zcHeight) ? $attrs.zcHeight : _json.height;
_json.width = ($attrs.zcWidth) ? $attrs.zcWidth : _json.width;
_json.id = id;
//Set the box-model of the container element if the height or width are defined as 100%.
if(_json.width === "100%" && !$element.css('width')){
$element.css('width', '100%');
}
if(_json.height === "100%" && !$element.css('height')){
$element.css('height', '100%');
}
zingchart.render(_json);
}
you need to use defaults instead of theme : please check attached fiddle ,
let me know is it the same thing you are looking?
zingchart.render({
id : 'myChart',
data : $scope.data,
height : 300,
width : 500,
defaults: $scope.myTheme
});
https://jsfiddle.net/omix3379/4k0v06cL/
Thanks.
Related
I am trying to display and update a chart using the plugin http://workshop.rs/jqbargraph/. The plugin is initiated on page load but I need to allow users to update the data that powers the chart. However, this functionality adds multiple charts everytime the update event is initiated. I assume I need to somehow destroy the original instance of the plugin before updating the chart data and re-initiating it but there is nothing incorporated into the plugin to allow this.
Can anyone tell me what I need to add to my code to get this working?
jQuery( document ).ready(function() {
var chartData = new Array([0]);
showChart(chartData);
jQuery('#update').live("click", function() {
var qtyArr = [];
jQuery('input[name=qty]').each(function(i) {
qty = Number(jQuery(this).val());
if(qty > 0){
qtyArr.push(qty);
}
});
chartData = new Array(
[qtyArr]
);
showChart(chartData);
});
});
function showChart(chartData){
jQuery("#chart").jqBarGraph({
data: chartData,
width: 200,
height: 300
});
}
call empty() before you call the plugin:
jQuery("#chart").empty().jqBarGraph({
data: chartData,
width: 200,
height: 300
});
The plugin's demo page clears the chart and reinitialises it as follows :
$('#exampleSimple').html('');
$('#exampleSimple').jqbargraph({ data: arrayOfData });
.empty() should also work.
You probably want -
function showChart(chartData) {
$('#chart').empty().jqBarGraph({
data: chartData,
width: 200,
height: 300
});
}
I'm using highcharts to draw chart dynamically on mouse over a table row. What i want is to clear out the chart out and hide the chart on mouse out.
I works fine in chrome but i get this strange behavior in firefox : The chart points remains there. I don't know if i'm clear enough. You can see this on http://dev.bluesquare.org/dev/data.
If you mouse over table with the title "National Quantities" you'll see a chart appearing on mouse over and disappearing on mouse out but leaving some dots on the table.
Is there anybody who can give me an idea about this problem.
Here is part of the code i'm using
$(function(){
$('#district-quantity table tbody tr').hover(function(){
var row_data = //get some data corresponding to the hovered row
var chartDiv = 'chart_div';
drawQuantityChart(row_data,chartDiv);
},function(){});
}
function drawQuantityChart(row_data,chartDiv) {
//call a function to parse and format the data for highcharts
var chartData = parseData(row_data);
var chart = new Highcharts.Chart({
chart : {
renderTo : chartDiv,
type : 'line',
height : 360
},
title : {
text : null
},
subtitle : {
text : null
},
xAxis : {
categories : chartData.periods
},
yAxis : {
title : {
text : null
},
gridLineWidth : 1,
min: 0
},
tooltip: {
followPointer: true
},
series : chartData.series
});
}
});
$('#district-quantity table tbody tr').hover(function(){
var row_data = //get some data corresponding to the hovered row
var chartDiv = 'chart_div';
drawQuantityChart(row_data,chartDiv);
},function(){
chart.destroy();
// Why don't you destroy your chart here? Make sure your chart variable is global.
});
}
I m really new in ExtJS and try to reuse some existing content produced with jQuery. Is there a simple way to add existing components as items in a container?
My code looks something like this
var rect = $('<div>', {
'id' : 'rectangle'
}).text("this is a rectangle.");
var cont = new Ext.Container({
layout : 'absolute',
width : 400,
height : 300,
renderTo : Ext.getBody(),
border : 1,
style : {
borderColor : '#000000',
borderStyle : 'solid',
borderWidth : '1px'
},
items : [{
html : rect
}]
});
Simply grab the html of that item with .html()
items : [{
html : rect.html()
}]
The best way is to use contentEl. Note that this moves the element inside the component, so when the component is destroyed, so is the element.
items: {
contentEl: rect.get(0) // Grab a reference to the DOM element
}
If you want to make a copy, of the element before moving it, you could call:
rect.clone.get(0);
I like to draw multiple charts on one page with using the same options but with different json data for each chart. I like to do this with as little code as possible, I really need to omit code duplication.
Here is the example of the first chart:
$(function() {
$.getJSON('login.php', function(data) {
var options= {
chart : {
renderTo : 'container'
},
rangeSelector : {
enabled:false
},
series : data
};
var chart = new Highcharts.StockChart(options);
});
});
How could I use this above code to create multiple charts using different getJSON data?
You could create a helper function:
$(function() {
var genOptions = function(data) {
return {
chart : {
renderTo : 'container'
},
rangeSelector : {
enabled:false
},
series : data
};
};
$.getJSON('login.php', function(data) {
var options = genOptions(data);
var chart = new Highcharts.StockChart(options);
});
$.getJSON('secondpage.php', function(data) {
var options = genOptions(data);
var chart = new Highcharts.StockChart(options);
});
});
You can follow the example as #blam, but with a slight change. Make sure the chart.renderTo value is different for each chart. From the above example I notice only one container value.
I have a problem when apply an Ext.ComboBox over an existing html select item, even if the existing content makes the html select about 20px (by it's content non static width is set), the Ext.ComboBox will resize to a sort of default, large, width value.
There's a way to auto resize the Ext.ComboBox based on the existing items and no using the default width?
Even if I know which best tool Ext is, this issue will let my colleagues to discard Extjs.
Thanks in advance
You can't technically make a combo "auto width" -- Ext actually converts the <select> into a regular <input> behind the scenes, and <input> elements have to have a width/size specified. However, you can trick Ext into sizing the combo based on the existing <select> which should give you the same end result. Here's an example from the Ext combo demo page, where I have modified the width config value:
var converted = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
transform:'state',
width: Ext.fly('state').getWidth(),
forceSelection:true
});
The obvious caveat would be that if you subsequently modify the list after it's rendered, the combo will not resize itself automatically and you'd have to figure out a way to resize it yourself.
Use this code:
Ext.ux.ResizableComboBox = Ext.extend(Ext.form.ComboBox, {
initComponent: function(){
Ext.ux.ResizableComboBox.superclass.initComponent.call(this);
this.on('render', this.resizeToFitContent, this);
},
resizeToFitContent: function(){
if (!this.elMetrics){
this.elMetrics = Ext.util.TextMetrics.createInstance(this.getEl());
}
var m = this.elMetrics, width = 0, el = this.el, s = this.getSize();
this.store.each(function (r) {
var text = r.get(this.displayField);
width = Math.max(width, m.getWidth(text));
}, this);
if (el) {
width += el.getBorderWidth('lr');
width += el.getPadding('lr');
}
if (this.trigger) {
width += this.trigger.getWidth();
}
s.width = width;
this.setSize(s);
this.store.on({
'datachange': this.resizeToFitContent,
'add': this.resizeToFitContent,
'remove': this.resizeToFitContent,
'load': this.resizeToFitContent,
'update': this.resizeToFitContent,
buffer: 10,
scope: this
});
}
});Ext.reg('resizable-combo', Ext.ux.ResizableComboBox);
In addition to what bmoeskau suggests, you can use an xtemplate for your combo's items. This will give you the ability to change the look of the item. You can wrap text, add images, etc.
add a listener to the afterrender event and set the width if the list (the div that drops down ) to auto e.g.
afterrender: function(combo){
combo.list.setSize('auto', 0);
combo.innerList.setSize('auto', 0);
}
The reason I am using afterrender and not render is because if you set lazyInit to false it will set the list width, so in afterrender you override that setWidth
I'm pretty sure you can get ExtJs to render whatever html items you need to, in the way you want them to be rendered.
here's some code from the Examples/Form/Combos.js file:
var converted = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
transform:'state',
width:20, //<-- set this config value!
forceSelection:true
});
in the code that you're using to transform the combo, just specify a width for the ExtJs combo.