google chart, php, ajax si mysqli nu functioneaza

Discutii si intrebari legate de scripturi si functii JavaScript, jQuery si Ajax, cod JavaScript in general.
sterica
Mesaje:285

google chart, php, ajax si mysqli nu functioneaza

Salutare,

Incerc sa realizez un chart pie dinamic (valori primite de la un dropdown) cu valori dintr-o baza de date.
M-am izbit de urmatoarea problema: dupa ce am inserat:

Cod: Selectaţi tot

if(isset($_POST['get_option'])){
  $sch = $_POST['get_option'];
  //...
}
nu imi mai apare graficul, doar ocupa spatiul setat prin div.

Am o daza de date denumita test ce contine o tabela tbl_teste avand urmatoarele coloane: id, nume, sales, anul.
Am un fisier query_chart_pie.php ce returneaza valori sub forma aceasta: ['popescu',369],['alin',124],

Cod: Selectaţi tot

<?php
include "bd_cnx.php";

   if(isset($_POST['get_option']))
   {
		 // Interogare SQL
		 $sch = $_POST['get_option'];
		 $sql = "SELECT nume, sales
		 FROM tbl_teste
		 WHERE anul = '$sch' ";

		 // Executa interogarea si retine datele returnate
		 $result = $conn->query($sql);

		 // daca $result contine cel putin un rand
		 if ($result->num_rows > 0) {

		 // afiseaza datele din fiecare rand din $result
		     while($row = $result->fetch_assoc()) {
		         echo "['".$row['nume']."',".$row['sales']."],";
		     }
		 } else {
		     echo "0 results";
		 }

		 // Se inchide conexiunea
		 $conn->close();
   }
	 else {
		 print "nu exista valori in post";
	 }
?>
Si mai am un fisier index.php ce contine chartul pie:

Cod: Selectaţi tot

<!doctype html>
<html>
    <head>
      <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
      <script type="text/javascript" src="jQuery.js"></script>
      <script type="text/javascript">

      function fetch_select(val)
      {
         $.ajax({
           type: 'post',
           url: 'query_chart_pie.php',
           data: {
             get_option:val
           },
           success: function (response) {
             document.getElementById("new_select").innerHTML=response;
           }
         });
      }
      </script>


      <script type="text/javascript">
        google.charts.load('current', {'packages':['corechart']});
        google.charts.setOnLoadCallback(drawChart);
        function drawChart() {
          var data = google.visualization.arrayToDataTable([
            ['Task', 'Hours per Day'],
            <?php include "query_chart_pie.php" ?>
          ]);
          var options = {
            title: 'My Daily Activities'
          };
          var chart = new google.visualization.PieChart(document.getElementById('piechart'));
          chart.draw(data, options);
        }
      </script>
    </head>


    <body style="background:gray;">
      <div id="piechart" style="width: 900px; height: 500px;"></div>
        <select onchange="fetch_select(this.value);">
   			<?php
    			$last_year = date ("Y");
    			for( $i = 2004; $i <= $last_year; $i++ ) {
        			$selected = ($last_year == $i) ? 'selected="selected"' : '';
        			echo "<option $selected value='$i'>$i</option>\n";
    			};
    		?>
        </select>
<div id="new_select"><?php include"query_chart_pie.php" ?></div>
  </body>
</html>
div-ul new_select l-am folosit mai mult ca test sa vad daca codul sql imi returneaza valorile dorite.

Unde gresesc de nu imi apare chart-ul (nu imi apare nici macar titlul, de legenda si valori nu mai vorbesc)
Multumesc!

MarPlo Mesaje:4343
Salut
In acel script sunt multe erori de logica:
1. Codul php e inclus in JavaScript la functia drawChart(), unde adauga un sir text in codul Javascript, ceea ce strica functionarea in continuare a codului JS.
- Daca fara apelare prin POST codul php nu returneaza ce e necesar la drawChart(), mai bine nu-l incluzi in JS.
2. Functia drawChart() ar trebui sa fie apelata din functia ajax, cu raspunsul /datele de la php.
3. La prelucrare de date intre php si javascript e bine sa lucrezi cu datele in format JSON.

Scriptul functional ar fi asa:
- query_chart_pie.php

Cod: Selectaţi tot

<?php
include 'bd_cnx.php';

if(isset($_POST['get_option'])){
  //Array-ul cu datele care vor fi returnate, in format json
  $ret =[['Task', 'Hours per Day']];

  // Interogare SQL
  $sch = $_POST['get_option'];
  $sql = "SELECT nume, sales FROM tbl_teste WHERE anul = '$sch' ";

  // Executa interogarea si retine datele returnate
  $result = $conn->query($sql);

  // daca $result contine cel putin un rand
  if ($result->num_rows > 0){
  // adauga datele din fiecare rand din $result in $ret
    while($row = $result->fetch_assoc()){
      //floatval() transforma sirul numeric in numar
      $ret[] =[$row['nume'], floatval($row['sales'])];
    }
  }
  else {
    $ret[] =['', ''];
  }

  //returneaza datele ca json
  echo json_encode($ret);
}
- index.php

Cod: Selectaţi tot

<!doctype html>
<html>
<head>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="jQuery.js"></script>
<script>

function fetch_select(val){
 $.ajax({
   type: 'post',
   url: 'query_chart_pie.php',
   data: {
     get_option:val
   },
   success: function (response) {
     document.getElementById('new_select').innerHTML=response;
     drawChart( JSON.parse(response));
   }
 });
}

  google.charts.load('current', {'packages':['corechart']});
  google.charts.setOnLoadCallback(drawChart);
  function drawChart(data_v){
    var data = google.visualization.arrayToDataTable(data_v);
    var options = {
      title: 'My Daily Activities'
    };
    var chart = new google.visualization.PieChart(document.getElementById('piechart'));
    chart.draw(data, options);
  }
</script>
</head>
<body style="background:gray;">
<div id="piechart" style="width: 900px; height: 500px;"></div>
  <select onchange="fetch_select(this.value);">
<?php
$last_year = date ("Y");
for( $i = 2004; $i <= $last_year; $i++ ) {
  $selected = ($last_year == $i) ? 'selected="selected"' : '';
  echo "<option $selected value='$i'>$i</option>\n";
};
?>
  </select>
<div id="new_select"><?php include"query_chart_pie.php" ?></div>
</body>
</html>

sterica Mesaje:285
MarPlo multumesc foarte mult, am citit si am incercat zeci de variante si nu as fi reusit fara ajutorul d-voastra si explicatiile d-voastra, functioneaza perfect.
Sunt foarte la inceput in ceea ce priveste progamarea web si ma atrage foarte mult, mai ales ca imbin utilul cu placutul. Am de facut rapoarte de activitate la munca si sunt nevoit sa extrag valori din baze de date, iar excelul este depasit :)

Ma puteti ajuta cu mai multe detalii in ceea ce priveste Json si in cazul meu care sunt relatiile intre fisiere php, ajax si json. Va cer ajutorul in privinta asta pentru ca ma uit in codul d-voastra si am intrat putin in ceata.

Pe aceasta cale vreau sa va multumesc foarte mult pentru site-ul d-voastra, am invatat foarte multe.

MarPlo Mesaje:4343
Daca vrei sa inveti despre JSON, iti pot fi de folos tutorialele:
- https://marplo.net/javascript/json-js
- https://marplo.net/ajax/tutoriale_ajax_json.html

Poti sa gasesti si pe internet la cautare: "json javascript php".

sterica Mesaje:285
Multumesc foarte mult. O sa aprofundez mai mult tutorialele recomandate.

Cum as putea face ca atunci cand este deschis fisierul index.php sa imi incarce graficul potrivit selectiei default din dropdown (cazul de fata 2016)? Multumesc mult!

MarPlo Mesaje:4343
Incearca sa apelezi automat functia cu accesare ajax dupa crearea <select>-ului, cu valoarea setata in el. Ii trebuie un ID.

Cod: Selectaţi tot

<select id="sel_year" onchange="fetch_select(this.value);">
<?php
$last_year = date ("Y");
for( $i = 2004; $i <= $last_year; $i++ ) {
  $selected = ($last_year == $i) ? 'selected="selected"' : '';
  echo "<option $selected value='$i'>$i</option>\n";
};
?>
</select>
<div id="new_select"><?php include"query_chart_pie.php" ?></div>
<script>
var sel_year = document.getElementById('sel_year').value;
fetch_select(sel_year);
</script>

sterica Mesaje:285
Dupa ce am facut modificare propusa de tine graficul functioneaza perfect insa vreau sa ii aduc o impunatatire.
Am codurile urmatoare:
query_chart_column.php

Cod: Selectaţi tot

<?php
include 'bd_cnx.php';

if(isset($_POST['get_luna_inceput'],
         $_POST['get_an_inceput'],
         $_POST['get_luna_sfarsit'],
         $_POST['get_an_sfarsit'],
         $_POST['get_activitate']
         )){
  //Array-ul cu datele care vor fi returnate, in format json
  $ret =[['Test','Valori']];
  // Interogare SQL
  $sch_luna_inceput = $_POST['get_luna_inceput'];
  $sch_an_inceput = $_POST['get_an_inceput'];

  $sql = "SELECT
      .......
ORDER BY TOTAL DESC";

  // Executa interogarea si retine datele returnate
  $result = $conn->query($sql);
  // daca $result contine cel putin un rand
  if ($result->num_rows > 0){
  // adauga datele din fiecare rand din $result in $ret
  while($row = $result->fetch_assoc()){
    //floatval() transforma sirul numeric in numar
    $ret[] =[$row['JUDET'], floatval($row['TOTAL'])];
        }
  }
  else {
      echo "result 0";
  }

}
  //returneaza datele ca json
  echo json_encode($ret);
?>
Cand sql-ul returneaza 0 randuri, in loc de grafic imi apare result 0 ['Test','Valori'], cum pot face ca in loc de result 0 ['Test','Valori'] sa imi apara un text: "pentru aceasta perioada nu sunt valori".

Multumesc!

MarPlo Mesaje:4343
Incearca asa:
1. In php anuleaza partea cu:

Cod: Selectaţi tot

else {
  echo "result 0";
}
2. In JavaScript, in functia drawChart() verifici daca array-ul primit are mai mult de un rand; cam asa:

Cod: Selectaţi tot

function drawChart(data_v){
  var piechart = document.getElementById('piechart');
  if(data_v.length >1){
    var data = google.visualization.arrayToDataTable(data_v);
    var options = {
      title: 'My Daily Activities'
    };
    var chart = new google.visualization.PieChart();
    chart.draw(data, options);
  }
  else piechart.innerHTML ='pentru aceasta perioada nu sunt valori';
}

sterica Mesaje:285
Pentru aceasta bucatica de cod:

Cod: Selectaţi tot

<script type="text/javascript">
        google.charts.load('current', {'packages':['corechart']});
        google.charts.setOnLoadCallback(drawChart);
        function drawChart() {
          var data = google.visualization.arrayToDataTable([['Task', 'Hours per Day'], 
          									<?php include "query_chart_pie.php" ?>
         									    ]);
          var options = { title: 'My Daily Activities'};
          var chart = new google.visualization.PieChart(document.getElementById('piechart'));
          chart.draw(data, options);
        }
      </script>
Ai adaugat data_v

Cod: Selectaţi tot

<script>

function fetch_select(val){
 $.ajax({
   type: 'post',
   url: 'query_chart_pie.php',
   data: {
     get_option:val
   },
   success: function (response) {
     document.getElementById('new_select').innerHTML=response;
     drawChart( JSON.parse(response));
   }
 });
}

  google.charts.load('current', {'packages':['corechart']});
  google.charts.setOnLoadCallback(drawChart);
  function drawChart(data_v){
    var data = google.visualization.arrayToDataTable(data_v);
    var options = {
      title: 'My Daily Activities'
    };
    var chart = new google.visualization.PieChart(document.getElementById('piechart'));
    chart.draw(data, options);
  }
</script>
si functia function fetch_select(val) are acest val. Ma poti ajuta sa inteleg la ce ajuta data_v si val la ce ajuta functiile.
Multumesc!

Edit:
- if-ul Imi returneaza [['Test','Valori']].

MarPlo Mesaje:4343
Daca vrei ca scriptul php sa returneze altceva cand nu sunt randuri selectate, poti face in codul php asa:

Cod: Selectaţi tot

echo (count($ret) >1) ? json_encode($ret) :'returneaza altceva';
- Despre Functii - Definire - Apelare gasesti explicatii in cursul JavaScript de pe site, la pagina: https://marplo.net/javascript/functii1.html

sterica Mesaje:285
am doua fetch_select: 1 si 2, primul fetch returneaza valorile pentru chart, iar al doilea pentru un total
fetch_select_1:

Cod: Selectaţi tot

function fetch_select_1(){
  document.getElementById('column_chart').style.display ='none';
  val_luna_inceput = $('#get_luna_inceput').val();
  val_an_inceput = $('#get_an_inceput').val();


  $.ajax({
    type: 'POST',
    url: 'Query_sql/query_chart_column.php',
    data: { get_luna_inceput: val_luna_inceput,
            get_an_inceput: val_an_inceput
    },
    success: function (response) {
      document.getElementById('column_chart').innerHTML=response;
      columnChart( JSON.parse(response));
    }
  });
}

function columnChart(data_v){...
si fetch_select_2:

Cod: Selectaţi tot

function fetch_select_2(){
  val_luna_inceput = $('#get_luna_inceput').val();
  val_an_inceput = $('#get_an_inceput').val();
  $.ajax({
    type: 'POST',
    url: 'Query_sql/query_chart_column_total.php',
    data: { get_luna_inceput: val_luna_inceput,
            get_an_inceput: val_an_inceput
    },
    success: function (response) {
      document.getElementById('odometer').innerHTML=response;
    }
  });
}
iar selecturile:

Cod: Selectaţi tot

<select id="get_luna_inceput" onchange="fetch_select_1(); fetch_select_2();"></select>
<select id="get_an_inceput" onchange="fetch_select_1(); fetch_select_2();"></select>
Ambele functii fetch_select_1 si 2 preiau valorile de la cele doua POST-uri get_luna_inceput si get_an_inceput.

Am nevoie ca la deschiderea paginii in browser functia din js sa imi selecteze automat valorile din selecturi.
Ma gandesc la o functie de genul:

Cod: Selectaţi tot

<script>
var sel_input = document.getElementById('get_luna_inceput, get_an_inceput ').value;
fetch_select_1(get_luna_inceput, get_an_inceput);
fetch_select_2(get_luna_inceput, get_an_inceput);
</script>

MarPlo Mesaje:4343
Ai putea folosi o singura functie fetchSelect() cu ajax.
Asa:

Cod: Selectaţi tot

<select id="get_luna_inceput"></select>
<select id="get_an_inceput"></select>
<script>
//gets the <select>s
var luna_inceput = document.getElementById('get_luna_inceput');
var an_inceput = document.getElementById('get_an_inceput');

//ajax function (url=php_file, callback=function to be accessed with response)
function fetchSelect(url, callback){
  var data = {get_luna_inceput: luna_inceput.value, get_an_inceput: an_inceput.value};
  $.ajax({
    type: 'POST',
    url: url,
    data: data
    },
    success: function (response){
      callback(response);
    }
  });
}

//creaate the chart with data_v response
function columnChart(data_v){
  document.getElementById('column_chart').innerHTML=data_v;
  var data_v = JSON.parse(data_v);
  //...
  
  //show #column_chart
  document.getElementById('column_chart').style.display ='block';
}

//register change event to <selects>s that calls the fetchSelect()
luna_inceput.addEventListener('change', function(e){
  document.getElementById('column_chart').style.display ='none';  //hides #column_chart
  fetchSelect('Query_sql/query_chart_column.php', columnChart);
});
an_inceput.addEventListener('change', function(e){
  fetchSelect('Query_sql/query_chart_column_total.php', function(resp){ document.getElementById('odometer').innerHTML=resp;});
});

//call fetchSelect() when page loads
fetchSelect('Query_sql/query_chart_column.php', columnChart);
fetchSelect('Query_sql/query_chart_column_total.php', function(resp){ document.getElementById('odometer').innerHTML=resp;});
</script>