how to fix this error Array to string conversion in laravel and chartjs? - laravel

i want to get sum men learning and women learning from learnings table and display to chart with group by province name.
Error:
Array to string conversion (View: C:\xampp\htdocs\project\resources\views\chart\index.blade.php)
my controller
$learnings =DB::table('provinces')
->join('learning_province','provinces.id','learning_province.province_id')
->join('learnings','learnings.id','learning_province.learning_id')
->select('title',\DB::raw('sum(men_learned + women_learned) as sum'))
->groupby('title')->whereYear('provinces.created_at', $year)->get();
$title = [];
$learning= [];
foreach ($learnings as $key => $value) {
$title[$key]=$value->title;
$learning[$key]=$value->sum;
}
return view('home.home', compact('learning', 'title'));
how to display sum men and women with group by province name in this script
my script
<script>
var ctx = document.getElementById('lineChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [{!!$title!!}],
datasets: [{
label: '# ',
data: [{!!$learning!!}],
backgroundColor: ["#3e95cd"],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>

However, instead of manually calling json_encode, you may use the #json Blade directive. The #json directive accepts the same arguments as PHP's json_encode function.
Please like this json_encode in laravel blade
<script>
var ctx = document.getElementById('lineChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: #json($title),
datasets: [{
label: '# ',
data: #json($learning),
backgroundColor: ["#3e95cd"],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>

Related

How can I display the product sales per month using a Line Graph?

$monthlySales = OrderProduct::selectRaw('sum(amount) as total_sales, month(created_at) as month, year(created_at) as year')
->groupBy('month', 'year')
->get();
$labels = $monthlySales->pluck('month')->toArray();
$data = $monthlySales->pluck('total_sales')->toArray();
This is the line graph:
var xValues = ['January','Febuary','March','April','May','June','July','August','September','October','November','December'];
var yValues = [{{$data}}];
new Chart("myChart", {
type: "line",
data: {
labels: xValues,
datasets: [{
fill: false,
lineTension: 0,
backgroundColor: "rgba(0,0,255,1.0)",
borderColor: "rgba(0,0,255,0.1)",
data: yValues
}]
},
options: {
legend: {display: false},
scales: {
yAxes: [{ticks: {min: 0, max:{{$sales}}}}],
}
}
});
I tried to use a for loop to make an array for the data but there's still no visible data, or maybe I don't have enough data in database?
you can change your yValue in js like:
var yValues = #json($data);
Works like a charm

How to sort time column in jsgrid?

We are binding a table using jqgrid. We have the first column start as a time column with a 12-hour format. We are facing an issue with sorting this data. The data is sorted correctly but it is not taking am/pm into consideration. Below is our code for binding the jqgrid:
var newFieldsArray =
[
{ name: "ID", title: "ID", type: "number", width: "50px", visible: false },
{
name: "TimeStart", title: "Start", type: "customTime", width: "100px", validate: "required",
sorttype: "date",
formatter : {
date : {
AmPm : ["am","pm","AM","PM"],
}
},
// datefmt: "m/d/Y h:i A",
//sorttype: 'datetime', formatter: 'date', formatoptions: {newformat: 'd/m/y', srcformat: 'Y-m-d H:i:s'},
insertTemplate: function () {
var $result = jsGrid.fields.customTime.prototype.insertTemplate.call(this); // original input
$result.val(varendTime);
return $result;
},
itemTemplate: function (value, item) {
return "<b style='display:none'>" + Date.parse(item.StartDate) + "</b><span>" + (item.TimeStart) + "</span>";
}
},
{
name: "TimeEnd", title: "End", type: "customTime", width: "100px", validate: "required",sorttype: "date", datefmt: "h:i"
},
{ name: "TimeTotal", title: "Time", type: "text", width: "50px", readOnly: true },
{
name: "CoilPO", title: "Coil PO", type: "text", width: "50px", validate: "required",
insertTemplate: function () {
var $result = jsGrid.fields.text.prototype.insertTemplate.call(this); // original input
$result.val(varlot);
return $result;
}
},
{ name: "Joints", title: "Joints", type: "integer", width: "60px" },
{ name: "CommercialGrade", title: "Commercial Grade", type: "integer", width: "80px" },
{ name: "QAHold", title: "QA Hold", type: "integer", width: "60px" },
{ name: "Rejected", title: "Reject", type: "integer", width: "60px" },
{ name: "ActionTaken", title: "Reason of Delay / Action Taken", type: "text", width: "120px" },
{
name: "ClassId", title: "Class",
type: "select", items: classDataArr,//classData.filter(function(n){return classdt.indexOf(n.Id) != -1 }),//classData,
valueField: "Id", textField: "Title",
insertTemplate: function () {
debugger;
var taxCategoryField = this._grid.fields[12];
var $insertControl = jsGrid.fields.select.prototype.insertTemplate.call(this);
var classId = 0;
var taxCategory = $.grep(voiceData, function (team) {
return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
});
taxCategoryField.items = taxCategory;
$(".tax-insert").empty().append(taxCategoryField.insertTemplate());
$insertControl.on("change", function () {
debugger;
var classId = parseInt($(this).val());
var taxCategory = $.grep(voiceData, function (team) {
return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
});
taxCategoryField.items = taxCategory;
$(".tax-insert").empty().append(taxCategoryField.insertTemplate());
});
return $insertControl;
},
editTemplate: function (value) {
var taxCategoryField = this._grid.fields[12];
var $editControl = jsGrid.fields.select.prototype.editTemplate.call(this, value);
var changeCountry = function () {
var classId = parseInt($editControl.val());
var taxCategory = $.grep(voiceData, function (team) {
return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
});
taxCategoryField.items = taxCategory;
$(".tax-edit").empty().append(taxCategoryField.editTemplate());
};
debugger;
$editControl.on("change", changeCountry);
changeCountry();
return $editControl;
}
},
{
name: "VoiceId", title: "Voice", type: "select", items: voiceData,
valueField: "Id", textField: "Title", width: "120px", validate: "required",
insertcss: "tax-insert",
editcss: "tax-edit",
itemTemplate: function (teamId) {
var t = $.grep(voiceData, function (team) { return team.Id === teamId; })[0].Title;
return t;
},
},
{ name: "Remarks", title: "Remarks", type: "text", width: "110px" },
{ name: "control", type: "control" }
];
hoursGrid.jsGrid("option", "fields", newFieldsArray);
Below is two screenshots of data that appear when we sort:
Can someone tell me what we are doing wrong?
You're mixing up jsGrid and jqGrid. The way to achieve it in jsGrid is using the built-in sorter jsGrid.sortStrategies.date, I added an example below.
As commented by #Tomy Tomov (the creator of jqGrid), you're using jsGrid, not jqGrid. This is evident both by your code and by the UI in the screenshot.
Specifically, you took the date sorter of jqGrid and used it in your jsGrid code, but (of course) it's not supported there. You can go ahead and look in jsGrid source for AmPm which you used - and see it's not there.
So how to do it in jsGrid?
Just pass the built-in sorter jsGrid.sortStrategies.date to the sorter property. However, it does require Date objects, so if you only got time strings, you'll have to convert those to dates.
Below is a quick demo (jsfiddle), click the date column title to sort:
Note that getData gets a function parameter that is responsible to get all data as Date objects, and that the value of isUTC depends on whether you actually use it
$(document).ready(function () {
const dataFunc = getDataTimes;
$("#jsGrid").jsGrid({
width: "100%",
data: getData(dataFunc),
sorting: true,
fields: [{
name: "name",
type: "text",
width: 50
}, {
name: "date",
type: "date",
width: 50,
sorter: jsGrid.sortStrategies.date,
cellRenderer: (value, item) => {
const withYear = false;
const isUTC = dataFunc == getDataTimes;
return renderDateTime(value, item, withYear, isUTC);
}
}
]
});
});
function getData(getDates) {
const data = [
{name: "a"}, {name: "b"}, {name: "c"},
{name: "d"}, {name: "e"}, {name: "f"},
];
const dates = getDates();
for (let i = 0; i < dates.length; i++) {
data[i].date = dates[i];
}
return data;
}
function getDataDates() {
const date1 = new Date(2022, 10, 1, 4, 50);
const date2 = new Date(2022, 10, 1, 8, 50);
const date3 = new Date(2022, 10, 1, 15, 50);
const date4 = new Date(2021, 10, 1, 4, 50);
const date5 = new Date(2021, 10, 1, 8, 50);
const date6 = new Date(2021, 10, 1, 15, 50);
return [date1, date2, date3, date4, date5, date6];
}
function getDataTimes() {
const time1 = "3:50 AM";
const time2 = "8:50 AM";
const time3 = "4:50 AM";
const time4 = "3:50 PM";
const time5 = "8:50 PM";
const time6 = "4:50 PM";
const times = [time1, time2, time3, time4, time5, time6];
return times.map(t => convertTime12to24(t));
}
function convertTime12to24(time12h) {
const [time, modifier] = time12h.split(' ');
let [hours, minutes] = time.split(':');
if (modifier === 'PM') {
hours = parseInt(hours, 10) + 12;
}
return new Date(Date.UTC(2022,0,1,hours, minutes));
}
function renderDateTime(value, row, withYear, isUTC) {
return `<td>${getDateTimeAsString(value, withYear, isUTC)}</td>`;
}
function getDateTimeAsString(date, withYear, isUTC) {
var options = {
hour: 'numeric',
minute: 'numeric',
hour12: true
};
if (withYear) {
options.withYear = 'numeric';
}
if (isUTC) {
options.timeZone = 'UTC';
}
return date.toLocaleString('en-US', options);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid-theme.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.css" rel="stylesheet">
<div id="jsGrid" class="jsgrid"></div>
Let me give it a try, we have 2 options to perform Sorting operation in JsGrid:
1.Custom Field (Topic Name you can refer below link)
Reference Link :http://js-grid.com/docs/#grid-fields
In this, you can define custom property in your config and extend it.
You can use sorter property and call your user defined function werein you can logic to sort date with time stamps directly.
2.Sorting Strategies (Topic Name you can refer below link)
Reference Link :http://js-grid.com/docs/#grid-fields
In this, you can create your custom objects and then apply sorting strategies of date directly on to the object to perform sorting operation as per your logic.

i want the line graph to start at 12:00AM and end at 11:59pm in chart js

i want my chart start at 12:00am and only draw the points when data avaiable. In most of my case data starts at 06:00am. now i want the chart look likes this.
i had generate the label from the created_at provide by the query. so, the label are equavalent to all the created_at present. My chart looks like this.
i want my label to start at 12:00Am but graph from the first created_at point. or null value can be replaced as 0.
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script>
let labels = {!! $labels !!};
Chart.defaults.scale.gridLines.drawOnChartArea = false;
Chart.defaults.global.title.display = true;
Chart.defaults.global.tooltips.intersect = false;
Chart.defaults.global.elements.point.radius = 0;
Chart.defaults.scale.ticks.maxTicksLimit = 21;
Chart.defaults.scale.ticks.maxRotation = 0;
Chart.defaults.scale.ticks.minRotation = 0;
Chart.defaults.global.defaultFontColor = "#bfbfbf";
var outdoor = new Chart(document.getElementById("outdoor").getContext('2d'), {
type: 'line',
showScale: false,
data: {
labels: labels,
datasets: [{
data: {{$activeGraph->pluck('status')}},
label: "Active Status",
borderColor: "#00F",
fill: false,
borderWidth: 1,
}]
},
options: {
title: {
text: 'Outdoor Temperature and Due Point'
},
customLine: {
color: 'black'
},
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
ticks: {
maxRotation: 0,
minRotation: 0
}
}]
}
},
</script>
my laravel code
$activeGraph = ActiveGraph::where('device_id', $id)->get();
$labels = $activeGraph->map(function ($model) {
return [$model->created_at->format('M-d') ,$model->created_at->format('h:i A')];
});
return view('devices.chart',compact('labels','activeGraph'))->with('device', $device);

highcharts line graph with ajax

I would like to implement a simple line graph with ajax in which only two points
x will be the hours and y will be the count of calls.
CODE :
<script>
function getData() {
$.ajax({
type:'POST',
url: "http://localhost/demo_chart/test.php",
dataType: 'JSON',
success: function(response_data) {
new_data = $.map(response_data, function(i){
return {x: i['date'],y: i['count']};
});
$('#container').highcharts({
chart: {
renderTo: 'container',
type: 'line'
},
title: {
text: 'Count vs. Time'
},
xAxis: {
title: {
text: 'Time'
},
type: 'Time',
},
yAxis: {
title: {
text: 'Count'
}
},
series: [{
name: 'Test',
data: new_data
}]
});
}
})
}
$(document).ready(function () {
getData();
})
</script>
Output of http://localhost/demo_chart/test.php is same as below :
{"date":["13:00:00","13:00:01","13:00:02","13:00:03","13:00:04"],"count":["1","2","3","4","2"]}
But still graph is not generating. So i would like to know what is the problem here.
Anyone like to share some hint which can resolve this problem ?
Expected output is :
X- axis : show all date
Y-axis : show count
You need to correct your mapping function, for example:
var response = {
"date": ["13:00:00", "13:00:01", "13:00:02", "13:00:03", "13:00:04"],
"count": ["1", "2", "3", "4", "2"]
};
new_data = $.map(response.date, function(el, index) {
return {
name: el,
y: parseInt(response['count'][index])
};
});
Additionally, with that data structure, I recommend you to use category axis type.
xAxis: {
...,
type: 'category'
}
Live demo: http://jsfiddle.net/BlackLabel/ptx6fy2q/
API Reference: https://api.highcharts.com/highcharts/xAxis.type

Populate three highchart graphics with one ajax call

I am trying to figure out how to combine 3 ajax call into 1 but so far I didn't find out the correct way to do it. I have the following three highcharts:
chart1 = new Highcharts.Chart({
chart: {
height: 155,
renderTo: 'chart1_div',
defaultSeriesType: 'spline',
events: {
load: GetData1(date)
}
},
plotOptions: {
series: {
fillOpacity: 0.1
}
},
xAxis: {
categories: c,
labels: {
staggerLines: 2
}
},
yAxis: {
gridLineColor: "#ffffcc",
title: {
text: ''
},
labels: {
x: 15,
y: 15,
style: {
color: "#999999",
//fontWeight: "bold",
fontSize: "10px"
}
},
},
series: [{
name: 'Chart1',
color: "#6bd9ec", //37f312
data: chart1_data
}]
});
chart2 = new Highcharts.Chart({
chart: {
height: 155,
renderTo: 'chart2_div',
defaultSeriesType: 'spline',
events: {
load: GetData2(date)
}
},
plotOptions: {
series: {
fillOpacity: 0.1
}
},
xAxis: {
categories: c,
labels: {
staggerLines: 2
}
},
yAxis: {
gridLineColor: "#ffffcc",
title: {
text: ''
},
labels: {
x: 15,
y: 15,
style: {
color: "#999999",
//fontWeight: "bold",
fontSize: "10px"
}
},
},
series: [{
name: 'Chart2',
color: "#6bd9ec", //37f312
data: chart2_data
}]
});
chart3 = new Highcharts.Chart({
chart: {
height: 155,
renderTo: 'chart3_div',
defaultSeriesType: 'spline',
events: {
load: GetData3(date)
}
},
plotOptions: {
series: {
fillOpacity: 0.1
}
},
xAxis: {
categories: c,
labels: {
staggerLines: 2
}
},
yAxis: {
gridLineColor: "#ffffcc",
title: {
text: ''
},
labels: {
x: 15,
y: 15,
style: {
color: "#999999",
//fontWeight: "bold",
fontSize: "10px"
}
},
},
series: [{
name: 'Chart3',
color: "#6bd9ec", //37f312
data: chart3_data
}]
});
At the moment I am making three different ajax calls:
function GetData1(date) {
$.ajax({
url: '/GetAjaxCall',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ date: date }),
success: function (f) {
var cat= [];
var ser= [];
$.each(f.d, function (i, e) {
cat.push(e.date);
ser.push(parseInt(e.val1));
});
chart1_div.xAxis[0].setCategories(cat);
chart1_div.series[0].setData(ser);
},
error: function (e) {
alert(e.statusText);
},
cache: false
});
}
function GetData2(date) {
$.ajax({
url: '/GetAjaxCall',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ date: date }),
success: function (f) {
var cat= [];
var ser= [];
$.each(f.d, function (i, e) {
cat.push(e.date);
ser.push(parseInt(e.val2));
});
chart2_div.xAxis[0].setCategories(cat);
chart2_div.series[0].setData(ser);
},
error: function (e) {
alert(e.statusText);
},
cache: false
});
}
function GetData3(date) {
$.ajax({
url: '/GetAjaxCall',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ date: date }),
success: function (f) {
var cat= [];
var ser= [];
$.each(f.d, function (i, e) {
cat.push(e.date);
ser.push(parseInt(e.val3));
});
chart3_div.xAxis[0].setCategories(cat);
chart3_div.series[0].setData(ser);
},
error: function (e) {
alert(e.statusText);
},
cache: false
});
}
As you can see, I am right now making the same ajax call 3 times just to be able to populate the 3 charts differently. Does anyone know how could I generate exactly the same 3 charts but only make 1 ajax call? Thanks a lot
Something like:
function GetDataAll(date) {
$.ajax({
url: '/GetAjaxCall',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ date: date }),
success: function (f) {
var cat1= [];
var ser1= [];
var cat2= [];
var ser2= [];
var cat3= [];
var ser3= [];
$.each(f.d, function (i, e) {
cat1.push(e.date);
ser1.push(parseInt(e.val1));
});
chart1_div.xAxis[0].setCategories(cat1);
chart1_div.series[0].setData(ser1);
chart2_div.xAxis[0].setCategories(cat2);
chart2_div.series[0].setData(ser2);
chart3_div.xAxis[0].setCategories(cat3);
chart3_div.series[0].setData(ser3);
},
error: function (e) {
alert(e.statusText);
},
cache: false
});
}
Under the load event I could call GetData1(date) for the 3 charts but this way I will be hitting the ajax call 3 times. I am probably doing this the wrong way and must be a more efficient way. I will appreciate any thoughts, thank you so much
EDITED - LATEST UPDATE THAT WORKS BASED ON #WERGELD HELP
var chart1_options = {
chart: {
renderTo: 'chart1_div',
xAxis: {
categories: []
},
series: [{
name: 'Chart1',
color: "#6bd9ec"
}]
};
var chart2_options = {
chart: {
renderTo: 'chart2_div',
xAxis: {
categories: []
},
series: [{
name: 'Chart2',
color: "#6bd9ec"
}]
};
var chart3_options = {
chart: {
renderTo: 'chart3_div',
xAxis: {
categories: []
},
series: [{
name: 'Chart3',
color: "#6bd9ec"
}]
};
function GetDataAll(date) {
$ajax({..
chart1_options.xAxis.categories = cat1;
chart1_options.series[0].data = ser1;
chart2_options.xAxis.categories = cat2;
chart2_options.series[0].data = ser2;
chart3_options.xAxis.categories = cat3;
chart3_options.series[0].data = ser3;
var chart1 = new Highcharts.Chart(Highcharts.merge(options, chart1_options));
var chart2 = new Highcharts.Chart(Highcharts.merge(options, chart2_options));
var chart3 = new Highcharts.Chart(Highcharts.merge(options, chart3_options));
});
}
Here is some psuedo code to get you going. What you need to do is setup a chart option object that contains all the constant items among your charts:
var options = {
chart: {
height: 155,
defaultSeriesType: 'spline'
},
plotOptions: {
series: {
fillOpacity: 0.1
}
},
xAxis: {
categories: c,
labels: {
staggerLines: 2
}
},
yAxis: {
gridLineColor: "#ffffcc",
title: {
text: ''
},
labels: {
x: 15,
y: 15,
style: {
color: "#999999",
//fontWeight: "bold",
fontSize: "10px"
}
},
}
};
Next you do your ajax call and assign your series' data and title (and any other items) and create an object for each chart you want to create:
var chartOptions1 = {
chart: { renderTo: 'container1' },
series: []
};
var chartOptions2 = {
chart: { renderTo: 'container1' },
series: []
};
Next you do your code to get the chart data/name/etc that you want to have for each chart which I will not go into here. The next step is to then create your chart from the merged options:
var chart1 = new Highcharts.Chart(Highcharts.merge(options, chartOptions1));
var chart2 = new Highcharts.Chart(Highcharts.merge(options, chartOptions2));
This should do it. Again, it is psuedocode but you get the idea. Global options + merge are you friends. Full psuedocode here.

Resources