Output structures to javascript

I have been wondering what’s the best way to output / use data from structures inside javascript.
My main issue that the javascript syntax really wants to see commas at the end of each iteration except the last one. And if there’s a comma the whole javascript code breaks.

I’m trying to figure out the best way to use structures to enter some data to use in chart.js and my semi-manual iteration is quite messy … another thing would also be Numbers vs other Values, since numbers are not required to be in ‘number’ but values are. So i am having a rather rough time getting things done in an simple way.

    var <?php echo $data->uid() ?> = document.getElementById("chart<?php echo $data->uid() ?>");
    var chart<?php echo $data->uid() ?> = new Chart(<?php echo $data->uid() ?>, {
        type: 'line',
        data: {
          labels: ['label1','label2','label3'],
          datasets: [
    {
     label: 'Data 1',
      data: ['10','20','30']
    },
    {
      label: 'Data 2',
      data: ['30','12','6']
      }
    ]
  }
});       

and what would be the best strategy to save data into?
so we can have a dynamic chart (in this case a line) using different labels and data.

This stuff is kind of over my head (I am by no means a JS programmer or a PHP programmer), but isn’t this what json_encode is for? in this super simple route, I get a full list of all the pages in a site in a properly formatted JSON array in order to feed it into select fields to in blueprints:

  // Page Links
  array(
    'pattern' => 'pagelist.json',
    'action'  => function() {
      header('Content-type: application/json; charset=utf-8');
      $pages = site()->index()->visible();
      $json = array();

      foreach ($pages as $page) {
          $json[$page->autoid()->value()] = $page->title()->value();
      }

      echo json_encode($json);
    }
  ),

In this one im getting a list of all the pages in a particular format in order to parse the JSON file into Uncss via Node in order to clean up unussed CSS rules…

  array(
    'pattern' => 'uncss.json',
    'action'  => function() {
      header('Content-type: application/json; charset=utf-8');
      $pages = site()->index()->visible();
      $root = site()->find('home');
      $json = array();
      $json[] = (string)$root->url();

      foreach ($pages as $page) {
          $json[] = (string)$page->url();
      }
      echo json_encode($json);
    }
  ),

In short, i’m pretty sure you can stack up your various arrays and then pass them through json_encode which take care of that pesky last comma for you. You will need someone with a more powerful brain then mine like @texnixe to help you further with that :slight_smile:

json_encode would be my next move too, but i am already struggleing how to come up with the optimal way to arrange my blueprint to have everything tied together having a set (or variable) number of datasets, axis labeling (the first label array in above code) as well as each dataset having a label (maybe other parameters for styling) and a data array.

I think if it was me, id be tempted to go the CSV route for the data, and just setup blueprint fields for the chart type, other visual settings. Then you just upload the CSV to the page and have the template pick it up and JSON it . Theres plenty of CSV to JSON libraries out there.

There’s plenty of people who can’t format their data to CSV … so this is no solution. CSV offers no advantage over a Structure in Kirby.

Well Ive been googling around it seems you can go from Yaml to javascript object. You might be able to get away with reading the yaml directly and go from there to a JS object rather then jumping through hoops and loops trying to piece together the JSON throught PHP.

Infact i bet there is something in Kirbys toolkit that can read the yaml and have it ready to pass into something else…

Maybe these help…

https://nodeca.github.io/js-yaml/

https://getkirby.com/docs/cheatsheet/field-methods/yaml

With json and help i was able to get it done…

<?php 
    $count = 0;
    $legende = array();
    foreach($data->legende()->toStructure() as $entry){
        $legende[] = $entry->title()->value();
    }
    $chart = array();
    foreach($data->chart()->toStructure() as $charts){
        $chart[$count]['label'] = $charts->title()->value();
        foreach($charts->text()->split(',') as $tag){
            $chart[$count]['data'][] = $tag;
        }
        foreach($charts->background()->split(',') as $bgcolor){
            $chart[$count]['backgroundColor'][] = (string)ak_convert_hex2rgba($bgcolor,'1');
        }
        foreach($charts->border()->split(',') as $bordercolor){
            $chart[$count]['borderColor'][] = (string)ak_convert_hex2rgba($bordercolor,'1');
        }
        $chart[$count]['fill'][] = $charts->fill()->bool();
        $chart[$count]['borderWidth'][] = 10;
        $count++;
    }    
?>
// Inside JS
//....
   type: 'line',
       data: {
           labels:<?php echo json_encode($legende); ?>,
           datasets: <?php echo json_encode($chart); ?>
       },
//....
1 Like