Hey maybe this example can help you. I’m really bad explaining things so I’ll do my best hehe… with this code you can :
1- query a collection after a drop-down selection which change the data (chart) dynamically based on selection.
2-The background color of Bar Chart change after drop-down selection.
3-Populate a repeater after a ‘Click’ in a single bar to show a picture and a text element to get the data (string) of that bar clicked, will be: Namefield + " is " + Agefield + " years old"
Scenario:
-Collection Name: “my collection”
-3 Field: Name, Age, Picture
Elements on page:
1- html component (to show the chart)
2-dropdown (to filter the “Age” field)
3-text element (…just for text…) (collapsed on load)
4-repeater (to show a picture) (collapsed on load)
5-dataset for “my collection” and connected to a image element in repeater
Page Code:
import wixData from 'wix-data';
$w.onReady(() => {
filter("All"); // Filter your data on page load.
$w('#dropdown').onChange(() => {
let chartdata = $w('#dropdown').value;
filter(chartdata);
});
function filter(chartdata) {
wixData.query("mycollection")
.contains("age",chartdata)
.find()
.then((res) => {
let name = new Array()
let age = new Array()
for (let i = 0; i < res.length; i++) {
name[i] = res.items[i].name;
age[i] = res.items[i].age;
}
let data = [[age],[name],[chartdata]];
$w('#html1').postMessage(data);
console.log(data)
$w('#html1').onMessage(async(event) => {
if (event.data.type === 'ready') {
$w('#html1').postMessage(data);
}
if (event.data.type === 'click') {
$w("#text").text = event.data.label + " is " + event.data.value + " years old.";
let torepeater = `${event.data.label}`;
await $w('#datasetmycollection').setFilter(wixData.filter().eq("name",torepeater))
$w("#repeater").expand();
$w("#text").expand();
}
});
})
.catch((err) => {
let errorMsg = err;
});
}
});
HTML Code:
Be aware that you can customize the chart, in this case I change the bg color of bar, a tool-tip when hover over a bar and others smalls changes, anyway this is not relate to wix just read the documentation on Chartjs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
</head>
<body onLoad="ready()">
<canvas id="myChart" width="980" height="1650"></canvas>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: [],
datasets: [{
label: '',
data: [],//start empty
backgroundColor: 'rgba(255, 119, 0, 0.6)', borderColor: 'rgba(65, 65, 65, 1)',
borderWidth: 1}]
},
options: { maintainAspectRatio: false,
legend: {display: false},
tooltips: {callbacks: {
label: function(tooltipItem, data) {
return tooltipItem.xLabel.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }, }, },
scales: {
xAxes: [{
ticks: {
beginAtZero: true, callback: function(value, index, values) { return value.toLocaleString();
}
}
}],
},
onClick: handleClick
}
});
////everything above this is just pure chart customization//////////
///Now 'what' the charts do with the data it receives////
window.onmessage = function(event){
if (event.data && Array.isArray(event.data)) {
myChart.data.datasets[0].data = event.data[0][0];
myChart.data.labels = event.data[1][0];
myChart.data.datasets[0].label = event.data[2][0];
myChart.update();
}
else { console.log("HTML Code Element received a generic message:");
console.log(event.data);
}
////change bar bgcolor based on age selection in dropdown////
if (event.data[2][0] <= 20) { myChart.data.datasets[0].backgroundColor = "SlateBlue"; myChart.update();
}
else if (event.data[2][0] >= 50) { myChart.data.datasets[0].backgroundColor = "LightYellow"; myChart.update();
}
else { myChart.data.datasets[0].backgroundColor = 'rgba(255, 119, 0, 0.6)';
myChart.update();
console.log("HTML Code Element received a generic message:");
console.log(event.data[2][0]);
}
};
//// function to handles the Click event over the bar///
function handleClick(e){
var activeBars = myChart.getElementAtEvent(e);
var value = myChart.config.data.datasets[activeBars[0]._datasetIndex].data[activeBars[0]._index].toLocaleString();
var label = activeBars[0]._model.label;
////Send the data back to page to do something, in this case
////'ready' and 'click', if 'click' the text element get the //// label (Name) and the value (Age) and 'ready' to show the ///chart.
window.parent.postMessage({
"type":"click",
"label":label,
"value":value
} , "*");
}
function ready(){
window.parent.postMessage({"type":"ready"}, "*");
}
</script>
</body>
</html>
That is, Hopefully somebody else could explain the code better than me hehehe
Good luck!