Problem with a json array

Hello, i’ve a bit problem, maybe this is a Javascrip thing not related to Framework7 itself…

I get a json request with data in this way… this works inside de request function, but outside there is not data inside the varTest… I can display in the console.log the data when it’s inside de request function, but outside there is nothing inside the varTest…
Here is the code:
Thanks in advance

var varTest = { myEvents: [] };
      Framework7.request.json('http://i-dont-write-my-real-domail.com/testDB2.php', function (data2) {
        for(var i=0 ; i < data2['myEvents'].length ; i++) {
          var x = varTest['myEvents'].push(data2['myEvents'][i]);
        }
        // when I display here the lengh of varTest, it's full of data... I can display the whole data too...
        console.log("Length inside" + varTest['myEvents'].length);
      });
      // But here, outside, the length is just 0...
      // I would like to make things here, outside with the data...
      console.log("Length outside" + varTest['myEvents'].length);

Maybe the answer is easier than this… because i’m traying to use the varTest as a bridge to have the data outside… but it doesn’t work… In Framework7 Documentation i can see this:

app.request.get('somepage.html', function (data) {
  console.log(data);
});

But the “data” values can be used only inside the function (data) {}… And i want to use the requested data after in the code, not inside that function…
Sorry, i’m newbie and don’t write english very well too… :sweat_smile:
Thanks

request is async
so your engine execute your code like this:

  1. var varTest = { myEvents: [] };
  2. console.log(‘Length outside’,varTest[‘myEvents’].length);
  3. request

well, not really (it’s a little bit more complicated)
but you must take this behavior in consideration

I make a request of calendar data that i have inside the database, to fill the calendar with the events in the database…
after the request I’m trying to push the data into a variable and loop through the json array filling the calendar…
But after the request i dont have the data, and donk know how to do that…

you should update your calendar inside request.callback

post your real code
maybe i can help

The code of calendar.html is:

<template>

  <div class="page">
        <div class="navbar navbar-large-transparent">
          <div class="navbar-bg"></div>
          <div class="navbar-inner">
            <div class="left">
              <a href="#" class="link back">
                 <i class="icon icon-back"></i>
                 <span class="if-not-md">Back</span>
               </a>
              <a href="#" class="link icon-only panel-open" data-panel="left">
                <i class="icon f7-icons if-not-md">menu</i>
                <i class="icon material-icons md-only">menu</i>
              </a>
            </div>
            <div class="title sliding navbar-calendar-title"></div>
            <div class="right">
              <a class="link icon-only searchbar-enable" data-searchbar=".searchbar-components">
                <i class="icon f7-icons if-not-md">search</i>
                <i class="icon material-icons md-only">search</i>
              </a>
            </div>
            <div class="title-large">
              <div class="title-large-text navbar-calendar-title"></div>
            </div>
            <form data-search-container=".components-list" data-search-in="a" class="searchbar searchbar-expandable searchbar-components searchbar-init">
              <div class="searchbar-inner">
                <div class="searchbar-input-wrap">
                  <input type="search" placeholder="Search components"/>
                  <i class="searchbar-icon"></i>
                  <span class="input-clear-button"></span>
                </div>
                <span class="searchbar-disable-button if-not-aurora">Cancel</span>
              </div>
            </form>
          </div>
        </div>



    <div class="page-content">
          <div class="block">
            <p>Info calendario</p>
          </div>


      <div id="calendar" class="block block-strong no-padding no-margin no-hairline-top"></div>
      <div id="calendar-events" class="list no-margin no-hairlines no-safe-area-left">
        <ul>
          {{#each eventItems}}
            <li class="item-content">
              <div class="event-color" style="background-color: {{color}}"></div>
              <div class="item-inner">
                <div class="item-title">{{title}}</div>
                <div class="item-after">{{time}}</div>
              </div>
            </li>
          {{else}}
            <li class="item-content">
              <div class="item-inner">
                <div class="item-title text-color-gray">No events for this day</div>
              </div>
            </li>
          {{/each}}
        </ul>
      </div>
    </div>
  </div>
</template>
<style>
  #calendar, #calendar-events {
    height: 50%;
    box-sizing: border-box;
  }
  #calendar .calendar {
    height: 100%;
  }
  #calendar-events ul {
    height: 100%;
    overflow: auto;
  }
  #calendar-events .event-color {
    position: absolute;
    left: 0;
    top: 0;
    width: 8px;
    height: 100%;
  }
  @media (orientation: landscape) {
    #calendar {
      float: left;
    }
    #calendar, #calendar-events {
      height: 100%;
    }
    #calendar, #calendar-events {
      width: 50%;
    }
    #calendar-events {
      margin-left: 50% !important;
      border-left: 1px solid #eee;
    }
    .theme-dark #calendar-events {
      border-left-color: #282828;
    }
  }
</style>
<script>
  return {

    data: function () {
      var varTest = { events: [] };

      var date = new Date();
      var year = date.getFullYear();
      var month = date.getMonth();
      var day = date.getDate();
      var allEvents = {
        eventItems: [],
        today: new Date(year, month, day),
        events: []
      }

      Framework7.request.json('http://----mydomain---/prbDB2.php', function (data2) {
        for(var i=0 ; i < data2['events'].length ; i++) {
          var x = varTest['events'].push(data2['events'][i]);
        }
        console.log("length inside" + varTest['events'].length);

      for(var i=0 ; i < varTest['events'].length ; i++) {

        var varDate = new Date(varTest['events'][i]['date'].substring(0,10));
        var varHour = varTest['events'][i]['date'].substring(11,13);
        var varMinutes = varTest['events'][i]['date'].substring(14,16);
        var varTitle = varTest['events'][i]['title']
        var x = allEvents['events'].push({date: varDate, hours: varHour, minutes: varMinutes, title: varTitle, color: '#2196f3'});
      }
      console.log(allEvents);

      });
      console.log("length outside" + varTest['events'].length);


      return allEvents;
    },
    methods: {
      renderEvents: function (calendar) {
        var self = this;
        var currentDate = calendar.value[0];
        var currentEvents = self.events
          .filter(function (event) {
            return (
              event.date.getTime() >= currentDate.getTime() &&
              event.date.getTime() < currentDate.getTime() + 24 * 60 * 60 * 1000
            );
          });

        const eventItems = [];
        if (currentEvents.length) {
          currentEvents.forEach(function (event) {
            const hours = event.hours;
            let minutes = event.minutes;
            if (minutes < 10) minutes = `0${minutes}`;
            eventItems.push({
              title: event.title,
              time: `${hours}:${minutes}`,
              color: event.color,
            });
          });
        }
        self.$setState({
          eventItems: eventItems,
        });
      },
    },
    on: {
      pageInit: function (e, page) {
        var self = this;
        var app = self.$app;
        var $ = self.$;
        var monthNames = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto' , 'Septiembre' , 'Octubre', 'Noviembre', 'Diciembre'];
        self.calendar = app.calendar.create({
          containerEl: '#calendar',
          toolbar: false,
          value: [self.today],
          events: self.events,
          on: {
            init: function (calendar) {
              $('.navbar-calendar-title').text(monthNames[calendar.currentMonth] +', ' + calendar.currentYear);
              app.navbar.size(app.navbar.getElByPage(page.el));
              calendar.$el.addClass('no-safe-area-right');
              self.renderEvents(calendar);
            },
            monthYearChangeStart: function (calendar) {
              $('.navbar-calendar-title').text(monthNames[calendar.currentMonth] +', ' + calendar.currentYear);
              app.navbar.size(app.navbar.getElByPage(page.el));
            },
            change: function (calendar) {
              self.renderEvents(calendar);
            },
          }
        });
      },
      pageBeforeRemove() {
        var self = this;
        self.calendar.destroy();
      },
    },
  }
</script>

The PHP file returns a json object like this:

{ "events" : [{ "id":"1", "title":"event n1", "date":"2020-03-03 13:00:00" } ,{ "id":"2", "title":"event n2", "date":"2020-03-06 13:30:00" } ,{ "id":"3", "title":"event n3", "date":"2020-03-12 15:00:00" } ,{ "id":"4", "title":"event n4", "date":"2020-03-08 16:30:00" } ,{ "id":"5", "title":"event n5", "date":"2020-03-16 20:30:00" } ,{ "id":"6", "title":"event n6", "date":"2020-03-13 09:00:00" } ] }

I’m working making changes in a Framework7 default template, in the default calendar sample… Solving problems step by step learning in the way… after that I need to make the reloading of data when the month changes… but first i’ve need to learn how to get the data from the database and request it in framework 7… step by step…
Now the calendar don’t show the events in the days, i can’t see what days have events, but when i click in a day it listed the events apart…

I’ve not write the most of the code… it’s just taked from the F7 example…
I’ve read something about the async request before, but I need to lear how to manage about it
Thanks a lot…

first remove all your extra code (all of it)
keep only the code from the source

#1 replace “data” with this:

data:function(){
  var date = new Date();
  var year = date.getFullYear();
  var month = date.getMonth();
  var day = date.getDate();
  return {
    eventItems: [],
    today: new Date(year, month, day),
    events: [],
    requested:[]
  }
}

#2 add this to “methods”

monthYearToString:function(y,m){
  var s = '0'+(m+1);
  return y+s.substr(s.length-2);   
},

#3 add also this to “methods” (change only the “url”)

getEvents:function(c,y,m){
  var self = this;
  var app = self.$app;
  var val = self.monthYearToString(y,m);
  if(self.requested.filter(function(i){
    return i==val;
  }).length){ return; } else { self.requested.push(val); }
  app.request({url:'url',method:'GET',dataType:'json',data:{date:val},
    success:function(data){
      data.events.map(function(itm){
        var i = itm.date.split(/[- :]/);
        return {
          id: itm.id, title: itm.title,
          date: new Date(i[0],i[1]-1,i[2]),
          hours: Number(i[3]),
          minutes: Number(i[4]),
          color: '#e91e63'
        }
      }).forEach(function(itm){ self.events.push(itm); });
      c.update();
    }
  });
},

#4 add some code to calendar obj (inside pageInit callback)

self.calendar = app.calendar.create({
 //keep params from source
 on:{
   init:function(calendar){
     // keep code from source
     // and add this:
     var val = calendar.value[0];
     self.getEvents(calendar,val.getFullYear(),val.getMonth());
   },
   // keep callbacks from source
   // and add this:
   monthYearChangeEnd:function(c,y,m){
     self.getEvents(c,y,m);
   }
 }
});

Thanks!!! It’s work fine except that when i change the month and return to the current the events are added other time… duplicated… if I repeat the month change… the events are triplicated, and so…

post again your code
or make sure that your request returns different result (month) for each request

right now i don’t send the month to the server yet, i only return event of March, I’m doing this step by step… but when i go to other month and return to March, the events added again but they have never been deleted before, so they are added twice… and tree times if i change month and return to march again… and so…
Despite there is no buttoms yet to change month, it can be changed sliding the calendar to the side…
So I’ve searched javascrip Array methods and i’ve find the pop() one, i will try to emty the array in the month change… prior to add the events…
and i need too to send the month in the request to the server to make the sql query acording to the month…
Righ now i’ve just the code you have give to me. I’m going to work from there… Your code is really helpful to understand how this work…

Lot of thanks.

i wrote it in a way that it will not request agian if it’s already “requested”
when you go to “april” it makes a new request for different month
and return the same result (as you said)

just return different result for each request
or (for test) change to this code;

app.request({url:'url',method:'GET',dataType:'json',data:{date:val},
  success:function(data){
    // remove this line when you ready
    c.params.events=self.events=[];
    // end
    data.events.map(function(itm){
      var i = itm.date.split(/[- :]/);
      return {
        id: itm.id, title: itm.title,
        date: new Date(i[0],i[1]-1,i[2]),
        hours: Number(i[3]),
        minutes: Number(i[4]),
        color: '#e91e63'
      }
    }).forEach(function(itm){ self.events.push(itm); });
    // remove this line when you ready
    c.params.events=self.events;
    // end
    c.update();
  }
});

just remember that it will only show events for “march” (according to your result)

how you send the month to the server there in your code…?. and how can I get it in the php?
My php file:

<?php

header('Access-Control-Allow-Origin: *');

$servername = "localhost";
$username = "my_dbusername";
$password = "my_dbpass";
$dbname = "my_dbname";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT prb01_id, prb01_txt, prb01_datetime FROM prb01";

$result = $conn->query($sql);

if ($result->num_rows > 0) {
    // Making Json String
    $salida = "{ \"events\" : [";

    $row = $result->fetch_assoc();

    while($row) {

        $salida = $salida . "{ \"id\":\"" . $row["prb01_id"]. "\", \"title\":\"" . $row["prb01_txt"] . "\", \"date\":\"" . $row["prb01_datetime"] . "\" }";


	    $row = $result->fetch_assoc();


	    if ($row) { $salida = $salida . " ,";}
    }
    $salida = $salida . " ] } ";
} else {
    $salida = "{ \"events\" : [ ] }";
}
echo $salida;

$conn->close();
?>

i’m not a php guy

i can only tell you that this line:
app.request({url:'file.php',method:'GET',dataType:'json',data:{date:'202003'},
will send to your server this line:
"file.php?date=202003"

Ok.
Lots of thanks @plpl !!! :+1: :+1: :+1:
I will manage, searching in manuals :face_with_monocle: I’ve does it till now… I’m newby in everything :sweat_smile:

it should be something like this

<?php
$stmt = $dbh->prepare("
  select 
  prb01_id id,
  prb01_txt title,
  prb01_datetime date 
  from prb01 
  where date=date_format(?,'%Y%m')
");
if ($stmt->execute(array($_GET['date']))) {
  while ($row = $stmt->fetch()) {
    print_r($row);
  }
}
?>

but i dont know if this is the right way
i just “googled”
you need to ask php guys

have fun

Hi @plpl
I’ve a question about your code:

    return {
      id: itm.id, title: itm.title,
      date: new Date(i[0],i[1]-1,i[2]),
      hours: Number(i[3]),
      minutes: Number(i[4]),
      color: '#e91e63'
    }

Here you subtrac 1 from the month number, here:

date: new Date(i[0], i[1]-1 ,i[2]),


and in this part of the code you add 1 to the month:

monthYearToString:function(y,m){
     var s = '0'+(m+1);
     return y+s.substr(s.length-2);   
},

here:

var s = ‘0’+( m+1 );


This means in the array the dates are stored with the months of the year begining in 0, instead of 1…
Why???
If this needed by Calendar component? i’ve read it begins the months in 1
If i change it by doing this in both places:

date: new Date(i[0], i[1] ,i[2]),

var s = ‘0’+( m );

The calendar changes the events and put them in the wrong month… put the april ones in march, march ones in april… and so…
Why this happens???
It’s another place in the code in with you add 1 to the month number…??? I’ve not find it…
I’m confused

Thanks for your answer

  1. do not change the code => this is how it should be
  2. the concept is very simple but my answer will be a little bit longer
    because i don’t speak english (i’ll try anyway)

back in the 70’s, when bell introduce the “C language” (which is the grandfather of javascript)
they thought that the “Date” object should be like this => Date([1970…],[0…11],[1…31])

why?
this is very simple:
while year and day are always numbers and they are the same in any language, the month is not.

now take a look at this code:

var timestamp = '2020-01-29 08:30:00';
var i = timestamp.split(/[- :]/);
console.log(i) // => ["2020", "01", "29", "08", "30", "00"]

var date = new Date(i[0],i[1]-1,i[2]); 
// => Date(2020,01-1,29) or Date(2020,0,29) 
var month = date.getMonth();
console.log(month) // => 0

var lang = {
  english: ['Jan','Feb','Mar','Apr','May','Jun'],
  spanish: ['Ene','Feb','Mar','Abr','May','Jun'],
  italian: ['Gen','Feb','Mar','Apr','Mag','Giu']
};

console.log('english month name',lang.english[month]) // => Jan
console.log('spanish month name',lang.spanish[month]) // => Ene
console.log('italian month name',lang.italian[month]) // => Gen

well, you may ask why they didn’t do it differently (month start with 1)
and then we could do something like this:

console.log('english month name',lang.english[month-1]) // => Jan
console.log('spanish month name',lang.spanish[month-1]) // => Ene
console.log('italian month name',lang.italian[month-1]) // => Gen

the answer is:
yes, you are absolutely right (i’m with you on this)
they could do it differently but they didn’t
and we will be stuck with their decision forever
get used to it

1 Like