I'm getting duplicate firestore data array using DataTables plugin - javascript

I'm using the DataTable plugin, populating the table with data from Firebase Firestore database.
But I'm getting multiple data-set arrays
which continues till it reaches the length of data in the db.
Also, getting some errors
DataTables warning: table id=dataTable - Requested unknown parameter '5' for row 0, column 5. For more information about this error, please see http://datatables.net/tn/4
and
DataTables warning: table id=dataTable - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3
But after I skip through all the errors, I get the Firestore data in the table.
Here is the code I'm using to get the data from Firestore and populating in the table;
$(document).ready(function () {
var dataSet = new Array();
var query = db.collection('news').orderBy('timestamp');
let observer = query.onSnapshot(snapshot => {
let changes = snapshot.docChanges();
changes.forEach(change => {
if (change.type == 'added') {
dataSet.push([change.doc.data().newsTitle,
change.doc.data().newsContent,
change.doc.data().newsImage,
change.doc.data().newsPublisher,
change.doc.data().timestamp.toDate()]);
console.log("data", dataSet);
const dataTable = $('#dataTable').DataTable({
data: dataSet,
order: [0, 'desc'],
columns: [
{ title: 'Title' },
{ title: 'Content' },
{ title: 'Picture' },
{ title: 'Publisher' },
{ title: 'Date' },
{ title: 'Action' }
]
});
dataTable.clear();
dataTable.rows.add(dataSet);
dataTable.draw();
}
})
});
})
What can I do to resolve this?

Figured it out, just removed the dataTable.rows.add(dataSet) from the loop.
$(document).ready(function () {
var dataSet = new Array();
var query = db.collection('news').orderBy('timestamp');
let observer = query.onSnapshot(snapshot => {
let changes = snapshot.docChanges();
changes.forEach(change => {
if (change.type == 'added') {
dataSet.push([change.doc.data().newsTitle,
change.doc.data().newsContent,
change.doc.data().newsImage,
change.doc.data().newsPublisher,
change.doc.data().timestamp.toDate()]);
}
})
console.log("data", dataSet);
const dataTable = $('#dataTable').DataTable({
data: dataSet,
order: [0, 'desc'],
columns: [
{ title: 'Title' },
{ title: 'Content' },
{ title: 'Picture' },
{ title: 'Publisher' },
{ title: 'Date' },
{ title: 'Action' }
]
});
dataTable.clear();
dataTable.rows.add(dataSet);
dataTable.draw();
});
})
But I'm still getting the alert error below twice, any ideas?
DataTables warning: table id=dataTable - Requested unknown parameter '5' for row 0, column 5. For more information about this error, please see http://datatables.net/tn/4

Related

How to split array and only save specific value into database? Laravel with Ajax

I have a question. I need to save array into database but I need to divide it first and only save specific value. I am using Ajax and pass the data to controller.
ps: the array set can be more than 1 so each set need to split and store based on columns inside DB.
my javascript that contain Ajax:
Hotspot.prototype.saveData = function (data) {
if (!data.length) {
return;
}
// Get previous data
var raw_data = localStorage.getItem(this.config.LS_Variable);
var hotspots = [];
if (raw_data) {
hotspots = JSON.parse(raw_data);
}
// Append to previous data
$.each(data, function (index, node) {
hotspots.push(node);
});
console.log(hotspots);
// var field=JSON.stringify(hotspots).split(',');
this.data=data;
$.ajax({
type:"POST",
url:"/store",
dataType:'json',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data:{
Title: JSON.stringify(hotspots),
Message: JSON.stringify(hotspots),
x: JSON.stringify(hotspots),
y: JSON.stringify(hotspots),
},
success: function(data){
console.log(data,d);
},
error: function(data)
{
console.log(data);
},
});
localStorage.setItem(this.config.LS_Variable, JSON.stringify(hotspots));
this.element.trigger('afterSave.hotspot', [null, hotspots]);
};
Controller:
public function storePin(Request $request)
{
request()->validate([
'Title' => 'required',
'Message' => 'required',
'x'=> 'required',
'y'=>'required',
]);
dd($request);
if ($request->all())
{
$pin = new Pin();
$pin->Title=json_encode($request->input('Title'));
$pin->Message= json_encode($request->input('Message'));
$pin->x = json_encode($request->input('x'));
$pin->y =json_encode($request->input('y'));
$pin->save();
// return response()->json_encode($request);
}
}
example output:
Title: [{"x":58.333333333333336,"y":90.54545454545455,"Title":"hi","Message":"hi"}]
Message: [{"x":58.333333333333336,"y":90.54545454545455,"Title":"hi","Message":"hi"}]
x: [{"x":58.333333333333336,"y":90.54545454545455,"Title":"hi","Message":"hi"}]
y: [{"x":58.333333333333336,"y":90.54545454545455,"Title":"hi","Message":"hi"}]
based on this I only want that it only store:
Title:only save title
Message:save message
x:save x
y save y
Just pass in the whole array of hotspots like:
data: hotspots,
Then in your model do any formatting and insert many:
// some formatting to create data array
$data = [];
foreach($hotspots as $hotspot){
$data[] = [
'Title' => $hotspot['Title'],
'Message' => $hotspot['Message'],
'x' => $hotspot['x'],
'y' => $hotspot['y'],
];
}
Pin::insert($data);
The problem appears to be parsing of data to hotspots. This method is iterating over each entry of data, then assigning the full node.
$.each(data, function(index, node) {
hotspots.push(node);
});
Each property definition is using the full hotspots object, as opposed to one property.
data: {
Title: JSON.stringify(hotspots),
Message: JSON.stringify(hotspots),
x: JSON.stringify(hotspots),
y: JSON.stringify(hotspots),
},
You probably need to do something like this:
{
Title: hotspots[0].Title,
Message: hotspots[0].Message,
x: hotspots[0].x,
y: hotspots[0].y,
}
Even still, this solution is missing some important information. For example, hotspots should be an array of hotspot objects...how do you know which one you are going to send for the single request?

Unknown Parameter Error for Datatable with dynamic columns being displayed

It keeps throwing unknown parameter S.N. on row 0 column 0. This is shown twice and then it exits. The columns are fetched via ajax and so are the data.
The structure is constructed correctly. Checked it with the console.
But this error pops up and the datatables is empty.
The no.of columns are correct tho but without any data.
if (response.isOk == true)
{
var data = new Array();
var columns = JSON.parse(response.responseObject.columns);
var counter = 1;
$.each(response.responseObject.data, function(index, value)
{
var datum = new Array();
$.each(columns, function(ind, val)
{
if (val.data == "S.N.")
{
datum.push(counter);
}
else
{
datum.push(value[val.data]);
}
});
counter++;
data.push(datum);
});
if (tabReport != "")
{
tabReport.destroy();
}
tabReport = $("#tabReport").DataTable
(
{
dom: "Bfrtip",
columns: columns,
buttons:
[
{
extend: "excelHtml5",
text: 'Download',
titleAttr: "Excel"
}
],
data: data
}
);
}
`var columns =
[
[data: "asd"],
[data: "asd"],
[data: "asd"]
];`
This is the desired format for the data table.

Is there a way to use NumberFormat() formatter (Google Charts) in vue-google-charts vue.js wrapper

I have been tasked with formatting some columns in charts using vue-google-charts, a vue.js wrapper for Google Charts and I am not sure that 'NumberFormat()' is even supported in vue-google-charts.
First, if somebody knows if it is or isn't, I would like to know so I don't waste much time pursuing something that isn't possible. But if it is, I sure would love an example of how to do it.
What we are doing is returning our chart data from the database and passing it into this vue.js wrapper. We are creating several charts but there are columns that have commas in them we want to remove.
Please review the existing code. I am trying to implement this using #ready as documented in the docs for vue-google-charts.
vue-google-charts docs -> https://www.npmjs.com/package/vue-google-charts
Here is our existing code with a little framework of the onChartReady method already in place.
<GChart
v-if="chart.data"
id="gchart"
:key="index"
:options="{
pieSliceText: chart.dropDownPie,
allowHtml: true
}"
:type="chart.ChartType"
:data="filtered(chart.data, chart.query, chart.query_type)"
:class="[
{'pieChart': chart.ChartType == 'PieChart'},
{'tableChart': chart.ChartType == 'Table'}
]"
#ready = "onChartReady"
/>
And then ...
<script>
import { GChart } from 'vue-google-charts';
import fuzzy from 'fuzzy';
import 'vue-awesome/icons';
import Icon from 'vue-awesome/components/Icon';
export default {
components: {
GChart,
Icon
},
props: {
},
data() {
return {
charts: window.template_data,
selected: 'null',
selects: [],
chartToSearch: false,
directDownloads: {
'Inactive Phones' : {
'slug' : 'phones_by_status',
'search_by' : 2,
'search' : '/Inactive/'
},
'Active Phones' : {
'slug' : 'phones_by_status',
'search_by' : 2,
'search' : '/Active/'
},
}
}
},
created(){
for (let i in this.charts){
if( !this.charts[i].slug ) continue;
$.post(ajaxurl, {
action: 'insights_' + this.charts[i].slug,
}, (res) => {
console.log(res.data);
if (res.success) {
this.$set(this.charts[i], 'data', res.data);
}
});
}
// console.log(this.charts);
},
methods: {
onChartReady(chart,google) {
let formatter = new.target.visualization.NumberFormat({
pattern: '0'
});
formatter.format(data, 0);
chart.draw(data)
},
toggleChart(chart) {
jQuery.post(ajaxurl, {
'action': 'update_insight_chart_type',
'chartType': chart.ChartType,
'chartSlug': chart.slug
}, (res) => {
chart.ChartType = res.data
})
},
csvHREF(chart) {
return window.location.href + '&rr_download_csv=' + chart.slug + '&rr_download_csv_search_by=' + chart.query_type + '&rr_download_csv_search=' + chart.query.trim()
},
filtered(data, query, column) {
query = query.trim();
if (query){
let localData = JSON.parse(JSON.stringify(data));
let column_Headers = localData.shift();
localData = localData.filter((row)=>{
if( query.endsWith('/') && query.startsWith('/') ){
return new RegExp(query.replace(/\//g, '')).test(String(row[column]));
}
return String(row[column]).toLowerCase().indexOf(query.toLowerCase()) > -1;
});
localData.unshift(column_Headers);
return localData;
}
return data;
},
filterIcon(chart) {
chart.searchVisible = !chart.searchVisible;
chart.query = "";
setTimeout(()=>{
document.querySelector(`#chart-${chart.slug} .insightSearch`).focus();
}, 1);
}
}
}
document.getElementsByClassName('google-visualization-table')
If anybody can help in ANY way, I am all ears.
Thanks!
not familiar with vue or the wrapper,
but in google charts, you can use object notation in your data,
to provide the formatted values.
all chart types will display the formatted values by default.
google's formatters just simply do this for you.
so, in your data, replace your number values with objects,
where v: is the value and f: is the formatted value...
{v: 2000, f: '$2,000.00'}
see following working snippet...
google.charts.load('current', {
packages: ['table']
}).then(function () {
var chartData = [
['col 0', 'col 1'],
['test', {v: 2000, f: '$2,000.00'}],
];
var dataTable = google.visualization.arrayToDataTable(chartData);
var table = new google.visualization.Table(document.getElementById('chart_div'));
table.draw(dataTable);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

how to solve Trying to get property 'bids' of non-object error

I want to display data from bid table in a form of datatable. But I get this error
"Trying to get property 'bids' of non-object" if it doesn't have bids.The bids model is connected to auction model and the auction model is connected to media site model. How to make it display blank record if it doesn't have data.
Here is my controller:
<?php
namespace App\Http\Controllers;
use App\Auction;
use App\Bid;
use App\User;
use App\Media;
use App\MediaSite;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class MediaSiteController extends Controller
{
public function show(MediaSite $mediaSite)
{
$auction = $mediaSite->auction;
$bids = $auction->bids;
return view('admin.media-site.show', ['mediaSite' => $mediaSite,'auction' => $auction], compact('auction'));
}
My view:
<body>
<div id="datatable-bid"></div>
</body>
<script>
$(document).ready(function () {
var datatableBid = $('#datatable-bid').mDatatable({
// datasource definition
data: {
type: 'local',
source: {!! json_encode($auction->bids) !!},
pageSize: 10
},
// layout definition
layout: {
theme: 'default', // datatable theme
class: '', // custom wrapper class
scroll: false,
footer: false // display/hide footer
},
// column sorting
sortable: true,
pagination: true,
search: {
input: $('#panel-search')
},
// columns definition
columns: [
{
field: "price",
title: "Price",
}, {
field: "month",
title: "Month",
},{
field: "user_id",
title: "User Id",
}
]
});
</script>
Here is my error:
Trying to get property 'bids' of non-object
place following after $auction = $mediaSite->auction;
if($auction){
$bids = $auction->bids;
}else{
//put following line or whatever you need to do if there is no data comes
$auction = [];
}
In the show() function make these changes
$auction = $mediaSite->auction;
if($auction) {
$bids = $auction->bids;
} else {
$bids = [];
}
// now send $bids to view along with $auction
// may be like this
// return view(..., compact($auction, $bids));
Then, in your view make this change
// datasource definition
data: {
type: 'local',
source: {!! json_encode($bids) !!},
pageSize: 10
},
See if this helps.

Unable to create a delete button in Meteor using reactive-table

I building a sortable table in Meteor with Reactive-Table and having trouble getting my delete button to work for removing entries from the table.
Please see my javascript code below:
Movies = new Meteor.Collection("movies");
if (Meteor.isClient) {
Template.body.events({
"submit .new-movie": function (event) {
var title = event.target.title.value;
var year = event.target.year.value;
var genre = event.target.genre.value;
Movies.insert({
title: title,
year: year,
genre: genre
});
event.target.title.value = "";
event.target.year.value = "";
event.target.genre.value = "0";
return false;
}
});
Template.moviestable.events({
"click .deletebtn": function (event) {
Movies.remove(this._id);
}
});
Template.moviestable.helpers({
movies : function () {
return Movies.find();
},
tableSettings : function () {
return {
showFilter: false,
fields: [
{ key: 'title', label: 'Movie Title' },
{ key: 'year', label: 'Release Year' },
{ key: 'genre', label: 'Genre' },
{ key: 'edit', label: 'Edit', fn: function () { return new Spacebars.SafeString('<button type="button" class="editbtn">Edit</button>') } },
{ key: 'delete', label: 'Delete', fn: function () { return new Spacebars.SafeString('<button type="button" class="deletebtn">Delete</button>') } }
]
}
}
});
}
Can anyone tell me what I'm doing wrong?
In the reactive tables docs, there's an example of how to delete rows from the table. Adapting the example in the docs for your needs, your event should look like this:
Template.moviestable.events({
'click .reactive-table tbody tr': function (event) {
event.preventDefault();
var objToDelete = this;
// checks if the actual clicked element has the class `deletebtn `
if (event.target.className == "deletebtn") {
Movies.remove(objToDelete._id)
}
}
});
The problem you are having is that you are trying to find the _id property on the button click instead of the row click.
If you do console.log(this) on your button click event (as you have it in your question above) you will get something like this Object {key: "delete", label: "", fieldId: "2", sortOrder: ReactiveVar, sortDirection: ReactiveVar} which does not contain the property _id
It is easier to register the row click, where the row object is the actual document you are trying to delete, and then check if the event's target has the delete class you added.

Categories

Resources