ECharts refresh on data change - refresh

I'm currently working on an interactive chart which should calculate potential risk-factors of commercial project. I've been using Baidu ECharts for this, and got the graph working visually, but can't get the graph to update when data changes.
The data comes from an external questionnaire, which uses radiobuttons for the values and a checkbox to turn the whole set on and off.
<input type="checkbox" id="GPEbool" value="true"> Example Question 1</h4>
<form action="">
<input type="radio" id="polishedness" value="1"> Idea<br>
<input type="radio" id="polishedness" value="1"> Concept<br>
<input type="radio" id="polishedness" value="2"> Mockup<br>
<input type="radio" id="polishedness" value="5"> Prototype<br>
<input type="radio" id="polishedness" value="7"> Playable<br>
<input type="radio" id="polishedness" value="15"> Polish<br>
<input type="radio" id="polishedness" value="30"> Finished<br>
</form>
Now, the problem is getting the data into the graph. It gets the initially selected value right (when adding "checked" to one of them), but won't update after that.
data: [{ value: $('input[name=polishedness]:checked').val(), name: 'Design'}]
I've tried calling the refresh function whenever something changes, but it'll return refresh is not a function. I'm really at loss, and the Chinese documentation doesn't help me much :)
Any suggestions? Thanks in advance!

You have to call chartInstance.setOption() again with your new data.
I give you a small example:
// eChart is the chart instance!
echart.setOption({
// .... some configuration
series: [
{
type: "line",
name: "test",
data: [1,2,3,4,5,6]
}
]
})
After you changed the value of your select box, you have to catch that event, change the value of the configuration object and call chartInstance.setOption() again.
Therefore, it is sometimes advisable to save your complete configuration object and store your changes there.

You can use resize() method, for example
window.chartRadar = echarts.init(document.getElementById('echartId'));
window.chartRadar.setOption({
title: {
text: 'radar echart'
},
tooltip: {},
legend: {
data: ['data1', 'data2']
},
radar: {
// shape: 'circle',
name: {
textStyle: {
color: '#fff',
backgroundColor: '#999',
borderRadius: 3,
padding: [3, 5]
}
},
indicator: [
{ name: 'sales', max: 6500},
{ name: 'Administration', max: 16000},
{ name: 'Information Techology', max: 30000},
{ name: 'Customer Support', max: 38000},
{ name: 'Development', max: 52000},
{ name: 'Marketing', max: 25000}
]
},
series: [{
name: 'Budget vs spending',
type: 'radar',
// areaStyle: {normal: {}},
data : [
{
value : [4300, 10000, 28000, 35000, 50000, 19000],
name : 'data1'
},
{
value : [5000, 14000, 28000, 31000, 42000, 21000],
name : 'data2'
}
]
}]
});
Once you alreay make you echart you cloud use the method "resize()" for redraw the echar for example
window.chartRadar.resize();

If you are using Angular ,
You can also use the [merge] option to have the Chart responding for the value changes,
<div echarts [options]="initialValue" [merge]= "dynamicData" class="demo-chart"></div>
Reference : https://github.com/xieziyu/ngx-echarts#api
In your Module assign Initial Value as below,
initialValue: EChartOption = {
xAxis: {
type: 'time',
splitNumber : 20
},
yAxis: {
type: 'value',
name : '$',
nameLocation: 'middle'
},
series: [{
data : [],
type: 'line'
}]
}
and set the Dynamic value based on your data, Also initialize "this.dynamicData" before making the api calls to the external service
formDataforChart(backTestTrades) {
let i = 0;
for(let backTestTrade of backTestTrades){
let profitAndTime = [];
profitAndTime.push(backTestTrade.exitTime);
profitAndTime.push(backTestTrade.profitOrLoss);
this.eChartDataSeries.push(profitAndTime);
}
let data = {
data : this.eChartDataSeries,
type : 'bar'
};
this.dynamicData=this.initialValue;
this.dynamicData.series = [];
// Applying my dynamic data here
this.dynamicData.series.push(data);
}

Related

chartjs not update using select option in laravel

I have problem with my code that when I use select option in chartjs datasets
below is the html code
<div class="form-group">
<select name="tahun" id="tahun" class="form-control">
#for ($i = 2021; $i <= date('Y'); $i++)
<option #if ($i == date('Y')) <?php echo 'selected'; ?> #endif value="{{ $i }}">{{ $i }}</option>
#endfor
</select>
</div>
<div id="parent-canvas">
<canvas id="chartpendapatan" width="400" height="200"></canvas>
</div>
and the jquery code is below :
const ctxpendapatan = document.getElementById('chartpendapatan').getContext('2d');
const myChartpendapatan = new Chart(ctxpendapatan, {
type: 'bar',
data: {
labels: [],
datasets: [{
label: 'Pendapatan Desa',
data: [],
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
scales: {
y: {
beginAtZero: true
}
}
}
});
var getData = function() {
var tahun = $("#tahun").val();
$.ajax({
url: "{{ url('/grafik_pendapatan') }}" + '/' + tahun,
type: "GET",
dataType: "JSON",
success: function(data) {
$.each(data.result, function(id, value) {
myChartpendapatan.data.labels.push(value.nama_bidang);
myChartpendapatan.data.datasets[0].data.push(value.total_anggaran);
});
myChartpendapatan.update();
},
error: function() {
alert("Tidak Ada Data");
}
});
};
const brgy = document.getElementById('tahun');
brgy.addEventListener('change', getData);
the output of my code is :
It's the data after I select year 2021
but after I select again year 2022 the output below :
first time whe I click year 2021, display 4 data in chart because in the database there are four data. but after I click year 2022, the data in 2021 still exist and data 2022 display also. so my question how to not display previous data after I select another year?
You push to the labels and data array, if you dont want to show previous data you need to remove this data first or just entirly override the array:
success: function(data) {
myChartpendapatan.data.labels = [];
myChartpendapatan.data.datasets[0].data = [];
$.each(data.result, function(id, value) {
myChartpendapatan.data.labels.push(value.nama_bidang);
myChartpendapatan.data.datasets[0].data.push(value.total_anggaran);
});
myChartpendapatan.update();
},

Vue.js and django rest framework for implements a cascading dropdown list

I would need help building a request to my backend API.
I currently have a form with a drop down list. The data in this list comes from this.$Http.get('/ quality/api/affaires/')
Below this drop-down list, I have another list. This list, I would like it to be empty until the 1st is not selected, then it is implemented with data according to the selection above.
Backend side (Django) I have 2 models which are "Affaires" and "AffairesOfs". I used Serialize and I can therefore request each of these models via api/affaires and api/affairesofs
In the "AffairesOfs" model I have a foreignekey (idaffaire) on the id of the "Affaires" model.
Finally, I would like my second list to be made up of all the “affairesofs” linked to the “Affaires” selected.
For now, I have my 2 drop-down lists but I can't find a way to link the second to the first.
I tried different methods found on the internet (with the use of v-model, ...) but could not achieve a result.
I can't even get the value selected from the first list to display it in the console, or in a <span>. I think I need a change event on the first list which ask a getMethod with selected value in parameters ?
example of api/affaire :
{
"id": 1,
"nom": "HORS AFFAIRE",
"adresse": "15, rue de la Gibaudière",
"cp": "49183",
"ville": "Saint-Barthélémy d'Anjou",
"dessinateur": 0,
"conducteur": 0,
"chefdeprojet": null,
"cloture": 0
},
{
"id": 2,
"nom": "Suivi Production",
"adresse": null,
"cp": null,
"ville": null,
"dessinateur": null,
"conducteur": null,
"chefdeprojet": null,
"cloture": 0
},
example of api/affairesofs :
{
"id": 2,
"idaffaire": {
"id": 1042,
"nom": "Schlumberger",
"adresse": "",
"cp": "75007",
"ville": "Paris",
"dessinateur": null,
"conducteur": 6,
"chefdeprojet": 16,
"cloture": 1
},
"dateajout": "2015-12-14T15:08:46Z",
"statut": 2,
"type": 0,
"nom": "Chassis St Do R1 à R3",
"isanalise": 1,
"idpersonnel": 1
},
{
"id": 6,
"idaffaire": {
"id": 1045,
"nom": "LAVAL",
"adresse": "",
"cp": "53000",
"ville": "Laval",
"dessinateur": 3,
"conducteur": 9,
"chefdeprojet": 9,
"cloture": 1
},
and below there is my page :
<div id="starting">
<div class="container">
<div class="row">
<form class="form-group">
<label>N° d'affaire</label>
<select class="col" v-model="affaireSelected">
<option value="">Choisir :</option>
<option v-for="affaire in affaires" v-bind:value="affaire.id">${affaire.id} - ${affaire.nom}</option>
</select>
<span> Selectionné : {{ affaireSelected }}</span>
<label>N° d'OF</label>
<select class="col">
<option value="choisir">Choisir :</option>
<option v-for="of in ofs" :value="of.id">${of.id} - ${of.nom}</option>
</select>
<input type="submit" value="Valider" class="btn btn-success" />
</form>
</div>
</div>
<div class="loading" v-if="loading===true">Loading…/div>
</div>
<!-- vue.js files !-->
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-resource#1.3.5"></script>
<script type="text/javascript">
new Vue({
el: '#starting',
delimiters: ['${','}'],
data: {
ncs: [],
affaires: [],
ofs: [],
affaireSelected: '',
loading: false,
currentNc: {},
},
mounted: function() {
this.getAffaires();
this.getOfs();
},
methods: {
getAffaires: function() {
this.loading = true;
this.$http.get('/qualite/api/affaires/')
.then((response) => {
this.affaires =response.data;
this.loading = false;
})
.catch((err) => {
this.loading = false;
console.log(err);
})
},
getOfs: function() {
this.loading = true;
this.$http.get('/qualite/api/affairesOf/')
.then((response) => {
this.ofs =response.data;
this.loading = false;
})
.catch((err) => {
this.loading = false;
console.log(err);
})
},
}
});
</script>
Finally found a solution. I need to use a computed property juste like this :
computed: {
ofsByAffaire() {
return this.ofs.filter(oF => oF.idaffaire.id === this.affaireSelected.id);
}
},
then, I juste have to use this computed property on the template :
<select class="col">
<option value="choisir">Choisir :</option>
<option v-for="of in ofsByAffaire" :value="of.id">${of.id} - ${of.nom}</option>
</select>

Algolia - Search with a condition to look into an array of string

I am using rails and algolia gem with mongoid datastore.
I am sending data to algolia for a model Question. One of the doc example in Algolia system is
objectID: 5691e056410213a381000000
text: "what is #cool about your name Mr. John? #name #cool"
asked_to: ["565571704102139759000000", "i7683yiq7r8998778346q686", "kjgusa67g87y8e7qtwe87qwe898989"]
asked_by: "564a9b804102132465000000"
created_at: "2016-01-10T04:38:46.201Z"
card_url: "http://localhost:3000/cards/5691e056410213a381000000"
answerers: []
has_answer: false
requestor_count: 0
status: "active"
popularity_point: 0
created_at_i: 1452400726
_tags: ["cool", "name"]
I want to find all those documents, where it meets these two conditions:
1) text contains your name
2) asked_to contains i7683yiq7r8998778346q686
I am using Twitter's typeahead javascript library. And my UI's javascript to implement algolia search is as follows:
<input class="typeahead ui-widget form-control input-md search-box tt-input" id="typeahead-algolia" placeholder="Search questions" spellcheck="false" type="text" autocomplete="off" dir="auto" style="position: relative; vertical-align: top;">
$(document).on('ready page:load', function () {
var client = algoliasearch("APPLICATION_ID", "SEARCH_KEY");
var index = client.initIndex('Question');
$('#typeahead-algolia').typeahead(
{
hint: false,
highlight: true,
minLength: 1
},
{
source: index.ttAdapter({hitsPerPage: 10}),
displayKey: 'text'
}
).on('keyup', this, function (event) {
if (event.keyCode == 13) {
$('#typeahead-algolia').typeahead('close');
window.location.href = "/?keyword="+encodeURIComponent($('#typeahead-algolia').val());
}
});
$('.typeahead').bind('typeahead:select', function(ev, suggestion) {
window.location.href = suggestion.card_url;
});
});
So my question is:
This code works perfectly. But how to add condition for asked_to contains i7683yiq7r8998778346q686 in above javascript to filter out result.
You can use a facet filter on the asked_to attribute in your query.
You first need to declare the attribute asked_to as an attribute for faceting in your index settings and then pass asked_to:i7683yiq7r8998778346q686 as a facet filter in your query via the facetFiltersquery parameter.
When your index settings are changed, you can change your source to add the facetFilters parameter:
$('#typeahead-algolia').typeahead(
{
hint: false,
highlight: true,
minLength: 1
},
{
source: index.ttAdapter({hitsPerPage: 10, facetFilters: "asked_to:i7683yiq7r8998778346q686"}),
displayKey: 'text'
}
).on('keyup', this, function (event) {
if (event.keyCode == 13) {
$('#typeahead-algolia').typeahead('close');
window.location.href = "/?keyword="+encodeURIComponent($('#typeahead-algolia').val());
}
});

Chart.js : straight lines instead of curves

I'm using Chart.JS to plot a dataset,
However I got a smooth effect !
Here is the curve I've got :
Here is my code :
function plotChart(data, labels) {
var lineChartData = {
"datasets": [{
"data": data,
"pointStrokeColor": "#fff",
"fillColor": "rgba(220,220,220,0.5)",
"pointColor": "rgba(220,220,220,1)",
"strokeColor": "rgba(220,220,220,1)"
}],
"labels": labels
};
var myLine = new Chart(document.getElementById("canvas").getContext("2d")).Line(lineChartData);
}
How can I have straight lines instead of curves ?
Thank you
Solution for Version 1 (old charts version)
According to documentation on chartjs.org
you can set the 'bezierCurve' in options and pass it in when you create the chart.
bezierCurve: false
eg:
var options = {
//Boolean - Whether the line is curved between points
bezierCurve : false
};
var myLine = new Chart(document.getElementById("canvas").getContext("2d")).Line(lineChartData, options);
Update for version 2
According to updated documentation for Line Configuration in global options
Name Type Default Description
tension Number 0.4 Default bezier curve tension. Set to 0 for no bezier curves.
eg:
var options = {
elements: {
line: {
tension: 0
}
}
};
And also directly in the Dataset Structure by setting lineTension to 0 (zero).
Property Type Usage
lineTension Number Bezier curve tension of the line. Set to 0 to draw straightlines.
This option is ignored if monotone cubic interpolation is used.
Note This was renamed from 'tension' but the old name still works.
An example data object using these attributes is shown below.
var lineChartData = {
labels: labels,
datasets: [
{
label: "My First dataset",
lineTension: 0,
data: data,
}
]
};
You can use lineTension option to set the desired curve. Set 0 for straight lines. You can give a number between 0-1
data: {
datasets: [{
lineTension: 0
}]
}
Just to complete version compatibility and to add something to this nice thread here:
Still the same with chart.js v3.x.x
(which is not backwards compatible with v2.x.x -- however, lineTension stays unchanged within
data: { datasets: [{ lineTension: ... )
LineTension for chart.js v3.x.x
Following, you can Run the snippet with 10 buttons to play with different lineTensions (0 to 1) right here:
// for now, let's assume sample data
let sample_data = {
"Labels" : [
"2021-08-02",
"2021-08-03",
"2021-08-04",
"2021-08-05",
"2021-08-06"
],
"Values": [
6,
4,
3,
8,
2
]
};
// Draw chart
const ctx = document.querySelector('canvas').getContext('2d');
const myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: sample_data.Labels,
datasets: [{
label: 'LineTension Sample',
data: sample_data.Values,
lineTension: 0,
borderColor: 'rgba(0,255,0,1)',
backgroundColor: 'rgba(0,255,0,0.3)',
fill: true
}]
}
});
function lineTension(event) {
// Redraw the chart with modified lineTension
// a bit of 'button-cosmetics' here
// enabling all buttons
document.querySelectorAll('button').forEach(element => element.disabled = false);
// disabling the pressed button
event.target.disabled = true;
// setting programmatically the 'lineTension' here
myLineChart.data.datasets[0].lineTension = parseFloat(event.target.dataset.linetension);
myLineChart.update();
};
button {
color: blue;
}
button:disabled {
color: black;
background-color: rgba(0,255,0,0.3);
}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- gets you the latest version of Chart.js, now at v3.5.0 -->
<button onclick="lineTension(event)" data-linetension="0" disabled>0</button>
<button onclick="lineTension(event)" data-linetension="0.1">0.1</button>
<button onclick="lineTension(event)" data-linetension="0.2">0.2</button>
<button onclick="lineTension(event)" data-linetension="0.3">0.3</button>
<button onclick="lineTension(event)" data-linetension="0.4">0.4</button>
<button onclick="lineTension(event)" data-linetension="0.5">0.5</button>
<button onclick="lineTension(event)" data-linetension="0.6">0.6</button>
<button onclick="lineTension(event)" data-linetension="0.7">0.7</button>
<button onclick="lineTension(event)" data-linetension="0.8">0.8</button>
<button onclick="lineTension(event)" data-linetension="0.9">0.9</button>
<button onclick="lineTension(event)" data-linetension="1">1</button>
<canvas width="320" height="240"></canvas>
I have used lineTension to set the smoothness of the curve.
From the docs: lineTension receives a number, Bezier curve tension of the line. Set to 0 to draw straight lines. This option is ignored if monotone cubic interpolation is used.
Just make sure to test with different values how smooth you want the line.
For example:
var data = {
labels: ["Jan", "Feb", "Mar"],
datasets: [{
label: "Label 1",
lineTension: 0.2
}, {
label: "Stock B",
lineTension: 0.2
}
]
};
I think it's been updated to lineTension. Check the docs.
Chart.js v3.9.1 - property tension.
Link to documentation

Bloodhound - typeahead not showing suggestions that start with the typed search string

I've been troubleshooting this for couple hours to no avail.
Basically, in the following code, I get the right results from the remote suggestions provider,
var descuentos = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.nonword,
queryTokenizer: Bloodhound.tokenizers.nonword,
remote: {
url: 'http://localhost:30045/Home/Suggest?q=%QUERY&type=name&fuzzy=false',
wildcard: "%QUERY",
filter: function (items) {
return $.map(items, function (item) {
return {
value: item.NombreComercio
};
});
}
}
});
$('#bloodhound .typeahead').typeahead({
hint: true,
highlight: true,
minLength: 0
},
{
name: 'descuentos',
source: descuentos
});
<body>
<div id="bloodhound">
<input class="typeahead" type="text" placeholder="Comercio Adherido...">
</div>
</body>
But, when the suggestion STARTS WITH the search string, is not displayed... Ideas?
Thanks!
Add displayKey to typeahead datasets parameter.
$('#bloodhound .typeahead').typeahead({
hint: true,
highlight: true,
minLength: 0
},{
name: 'descuentos',
displayKey: 'value',
source: descuentos
});
Hope this helps.