I'm using AmCharts4 with Vue.JS,
For the moment I've added default chart design when page loads, But when I trying to add dynamic values after page loads (Using Button click), It doesn't reflect on view.
Code:- gist
data: () => ({
dataForChart: {
data: [{
"name": "Anne",
"steps": 32
}, {
"name": "Rose",
"steps": 30
}, {
"name": "Jane",
"steps": 25
}]
}
}),
chart creation on mounted()
let chart = am4core.create("chart-div", am4charts.XYChart);
chart.data = this.dataForChart.data
when dynamically change values using button click those data doesnt reflect on chart.
method followed to change data set.
this.dataForChart.data = {
data: [{
"name": "Anne",
"steps": 54
}, {
"name": "Rose",
"steps": 44
}, {
"name": "Jane",
"steps": 33
}]
}
The reason for this is that although this.dataForChart.data is reactive (it's a vue instance property) the chart.data (amcharts chart property) is not.
You have to manually set chart.data array values whenever your this.dataForChart.data property changes. I've done this by setting a watcher on this.dataForChart.data like so:
watch: {
dataForChart: {
data(values) {
this.chart.data = values;
},
deep: true
}
}
Cheers!
Related
I have a situation where I want to get the full (data) from the backend as a CSV file. I have already prepared the backend for that, but normally the front-end state => (filters) is not in contact with the backend unless I send a request, so I managed to solve the problem by mimicking the process of showing all data but by a custom button and a GET request ( not an ajax request ). knowing that I am using serverSide: true in datatables.
I prepared the backend to receive a request like ( Show All ) but I want that link to be sent by custom button ( Export All ) not by the show process itself as by the picture down because showing all data is not practical at all.
This is the code for the custom button
{
text: "Export All",
action: function (e, dt, node, config) {
// get the backend file here
},
},
So, How could I send a request like the same request sent by ( Show All ) by a custom button, I prepared the server to respond by the CSV file. but I need a way to get the same link to send a get request ( not by ajax ) by the same link that Show All sends?
If you are using serverSide: true that should mean you have too much data to use the default (serverSide: false) - because the browser/DataTables cannot handle the volume. For this reason I would say you should also not try to use the browser to generate a full export - it's going to be too much data (otherwise, why did you choose to use serverSide: true?).
Instead, use a server-side export utility - not DataTables.
But if you still want to pursuse this approach, you can build a custom button which downloads the entire data set to the DataTables (in your browser) and then exports that complete data to Excel.
Full Disclosure:
The following approach is inspired by the following DataTables forum post:
Customizing the data from export buttons
The following approach requires you to have a separate REST endpoint which delivers the entire data set as a JSON response (by contrast, the standard response should only be one page of data for the actual table data display and pagination.)
How you set up this endpoint is up to you (in Laravel, in your case).
Step 1: Create a custom button:
I tested with Excel, but you can do CSV, if you prefer.
buttons: [
{
extend: 'excelHtml5', // or 'csvHtml5'
text: 'All Data to Excel', // or CSV if you prefer
exportOptions: {
customizeData: function (d) {
var exportBody = getDataToExport();
d.body.length = 0;
d.body.push.apply(d.body, exportBody);
}
}
}
],
Step 2: The export function, used by the above button:
function GetDataToExport() {
var jsonResult = $.ajax({
url: '[your_GET_EVERYTHING_url_goes_here]',
success: function (result) {},
async: false
});
var exportBody = jsonResult.responseJSON.data;
return exportBody.map(function (el) {
return Object.keys(el).map(function (key) {
return el[key]
});
});
}
In the above code, my assumption is that the JSON response has the standard DataTables object structure - so, something like:
{
"data": [
{
"id": "1",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
},
{
"id": "2",
"name": "Garrett Winters",
"position": "Accountant",
"salary": "$170,750",
"start_date": "2011/07/25",
"office": "Tokyo",
"extn": "8422"
},
{
"id": "3",
"name": "Ashton Cox",
"position": "Junior Technical Author",
"salary": "$86,000",
"start_date": "2009/01/12",
"office": "San Francisco",
"extn": "1562"
}
]
}
So, it's an object, containing a data array.
The DataTables customizeData function is what controls writing this complete JSON to the Excel file.
Overall, your DataTables code will look something like this:
$(document).ready(function() {
$('#example').DataTable( {
serverSide: true,
dom: 'Brftip',
buttons: [
{
extend: 'excelHtml5',
text: 'All Data to Excel',
exportOptions: {
customizeData: function (d) {
var exportBody = GetDataToExport();
d.body.length = 0;
d.body.push.apply(d.body, exportBody);
}
}
}
],
ajax: {
url: "[your_SINGLE_PAGE_url_goes_here]"
},
"columns": [
{ "title": "ID", "data": "id" },
{ "title": "Name", "data": "name" },
{ "title": "Position", "data": "position" },
{ "title": "Salary", "data": "salary" },
{ "title": "Start Date", "data": "start_date" },
{ "title": "Office", "data": "office" },
{ "title": "Extn.", "data": "extn" }
]
} );
} );
function GetDataToExport() {
var jsonResult = $.ajax({
url: '[your_GET_EVERYTHING_url_goes_here]',
success: function (result) {},
async: false
});
var exportBody = jsonResult.responseJSON.data;
return exportBody.map(function (el) {
return Object.keys(el).map(function (key) {
return el[key]
});
});
}
Just to repeat my initial warning: This is probably a bad idea, if you really needed to use serverSide: true because of the volume of data you have.
Use a server-side export tool instead - I'm sure Laravel/PHP has good support for generating Excel files.
I have a computed property that pulls some data out of my vuex store like so:
computed: {...mapGetters(["allCategories"])},
Each category in this.allCategories looks like so:
{ "id": "123", "name": "Foo" }
I want to pull out every name field from this.allCategories before the component is mounted in put each name into an reactive data property called categoryNames.
How can I achieve this?
What I have tried so far is below:
beforeMount() {
for (let i = 0; i < this.allCategories.content.length; i++) {
var name = this.allCategories.content[i].name
this.categoryNames.push(name);
}
},
Which gives the following error:
Error in beforeMount hook: "TypeError: Cannot read property 'length' of undefined"
this.allCategories looks like so:
{
"content": [
{
"id": "efb038df-4bc9-4e31-a37a-e805c9d7294e",
"parentCategoryId": "8ffc214f-fff1-4433-aac9-34d13b4e06c5",
"name": "Foo"
},
{
"id": "5905d437-db2e-4f91-8172-c515577b86e9",
"parentCategoryId": "5905d437-db2e-4f91-8172-c515577b86e9",
"name": "Bar"
},
{
"id": "8ffc214f-fff1-4433-aac9-34d13b4e06c5",
"parentCategoryId": "8ffc214f-fff1-4433-aac9-34d13b4e06c5",
"name": "Baz"
}
],
"number": 0,
"size": 100,
"total": 3
}
You could use the created hook to call a vuex action that calls a vuex mutation that grabs a state, do your parsing and store the parsed data in a new array in state, then use a getter to grab the parsed array from state.
created() {
this.$store.dispatch('someAction');
},
computed: {
...mapGetters({
parsedArray: 'getParsedArray',
})
}
export const actions = {
someAction({ commit }) {
commit('SOME_MUTATION');
},
}
export const mutations = {
SOME_MUTATION(state) {
let data = state.originalData;
let parsedArray = [];
// Do parsing work here
state.parsedArray = parsedArray
},
}
export const getters = {
getParsedArray: state => {
return state.parsedArray;
},
}
I have a dataTables table at http://communitychessclub.com/test.php
My problem is I need to make an entire table row clickable to a link based on a game#. The table lists games and user should click on a row and the actual game loads.
I am unable to understand the previous solutions to this problem. Can somebody please explain this in simple terms?
I previously did this at http://communitychessclub.com/games.php (but that version is too verbose and does disk writes with php echo)
with
echo "<tr onclick=\"location.href='basic.php?game=$game'\" >";
<script>$(document).ready(function() {
$('#cccr').dataTable( {
"ajax": "cccr.json",
"columnDefs": [
{
"targets": [ 0 ],
"visible": false,
}
],
"columns": [
{ "data": "game" },
{ "data": "date" },
{ "data": "event" },
{ "data": "eco" },
{ "data": "white_rating" },
{ "data": "white" },
{ "data": "black_rating" },
{ "data": "black" }
]
} );
} );</script>
"cccr.json" looks like this and is fine:
{
"data": [
{
"game": "5086",
"date": "09/02/2013",
"event": "135th NYS Ch.",
"eco": "B08",
"white": "Jones, Robert",
"white_rating": "2393",
"black": "Spade, Sam",
"black_rating": "2268"
},
...
You can do it this way:
Use fnRowCallback to add a game-id data-attribute to your datatable rows
...
{ "data": "black" }
],
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
//var id = aData[0];
var id = aData.game;
$(nRow).attr("data-game-id", id);
return nRow;
}
This will give each row in your table a game id attribute e.g:
<tr class="odd" data-game-id="5086">
Then create a javascript listener for the click event and redirect to the game page passing the game id taken from the tr data-attribute:
$('#cccr tbody').on('click', 'tr', function () {
var id = $(this).data("game-id");
window.location = 'basic.php?game=' + id;
}
Surely it should be possible to issue the same query against the same store to populate a dGrid (or any other form of grid) and the dropdown in a filteringSelect with the same rows.
However it looks like the filteringSelect needs a response of the form
{
"identifier": "abbreviation",
"label": "name",
"items": [
{ "abbreviation": "AL", "name": "Alabama" },
{ "abbreviation": "AK", "name": "Alaska" },
{ "abbreviation": "WY", "name": "Wyoming" }
]
}
and the dgrid needs
[
{ "abbreviation": "AL", "name": "Alabama" },
{ "abbreviation": "AK", "name": "Alaska" },
{ "abbreviation": "WY", "name": "Wyoming" }
]
It seems that the identifier and label attributes coming from the store are completely superflous because you are getting the identifier via the identity API and in any case you can specify everything when you instantiate the filteringselect.
Yes I know there are work-arounds - I could use two different stores or queries and get the server-side to generate generate both of these based on some parameter in the query. But if I do this will the changes propagate properly when I make changes via the dgrid? or I could wrap the store API with something that puts the extra fields on the front of the response and pass the wrapped store into the filteringselect, but is there a simpler way?
Use your array to create a data store like:
var store = Observable(new Memory({
idProperty: "abbreviation",
data: [ {
"abbreviation": "AL", "name": "Alabama"
}, {
"abbreviation": "AK", "name": "Alaska"
}, {
"abbreviation": "WY", "name": "Wyoming"
}]
}));
Then, your can set this store to dgrid as :
dgrid.set('store', store);
For your filteringSelect, you can set this store as
new FilteringSelect({
searchAttr:"name",
store: store
});
I'm wonder is it possible to proper setting each xaxis in dojox.charting.DataChart
here is my data.JSON for example:
{
"label": "btmlabel",
"items": [
{ "mydata":"ANDT", "btmlabel":[{value: 1, text: "22 April 10.34AM"},{value: 2, text: "22 April 10.40AM"}], "data":[{"x":1,"y":1},{"x":2,"y":3}] }
]
}
and trying to draw xaxis which failed(show empty in xaxis) with below code:
var chartPrefs = {
chartPlot: {type:dojox.charting.plot2d.Markers, tension:"S"},
scroll:true,
xaxis:{labelFunc:"seriesLabels"},
}
chart = new dojox.charting.DataChart("chartNode", chartPrefs);
chart.setStore(store, {mydata:"*"}, "data");
});
It looks like your json object structure is invalid for charting. It would be better use the following structure:
var storeData = {
"label": "btmlabel",
"items":
[
{
"btmlabel": "22 April 10.34AM",
"data": 1
},
{
"btmlabel": "22 April 10.40AM",
"data": 3
}
]
}
and creating chart:
dojo.addOnLoad(function () {
var storeForChart = new dojo.data.ItemFileWriteStore({ data: storeData });
var chartPrefs = {
chartPlot: { type: dojox.charting.plot2d.Markers, tension: "S" },
comparative: true,
xaxis: { labelFunc: "seriesLabels" }
}
chart = new dojox.charting.DataChart("chartNode", chartPrefs);
chart.setStore(storeForChart, { data: "*" }, "data");
});
View source of this page - here working example.
Read good article about chart building - introducing-dojox-datachart
EDIT:
Also look this page. I think it will be very helpful for you.