juppix: Wieder mal: Problem mit JSON/Ajax

Hi zusammen,

ich habe (mal wieder) ein Problem(chen) mit meinem JSON-"Freund"! Da Ihr so perfekt unterstützt frage ich einfach mal wieder an...:

Ich möchte den "Bootstrap year calendar" an eine PHP-Ajax-Datenquelle "anhängen" (JSON denke ich mal).

Der Kalender wird wie folgt initialisiert:

  $('#calendar').calendar({ 
        enableContextMenu: true,
        enableRangeSelection: true,
        …
        …
        dataSource: [
            {
                id: 0,
                name: 'Google I/O',
                location: 'San Francisco, CA',
                startDate: new Date(currentYear, 4, 28),
                endDate: new Date(currentYear, 4, 29)
            },
            {
                id: 1,
                name: 'Microsoft Convergence',
                location: 'New Orleans, LA',
                startDate: new Date(currentYear, 1, 16),				
                endDate: new Date(currentYear, 1, 16)
            },
           …
           …

Nun gibt es beim Googeln auch viele Infos um den Kalender an AJAX anzubinden, z. B.: https://github.com/Paul-DS/bootstrap-year-calendar/issues/21

... aber ich kriege es wieder einfach nicht hin.

Soweit bin ich bereits (wie bei dem Link oben erklärt):

           …
           …
            },
            {
                id: 9,
                name: 'LA Tech Summit',
                location: 'Los Angeles, CA',
                startDate: new Date(currentYear, 10, 17),
                endDate: new Date(currentYear, 10, 17)
            }
        ],
		yearChanged: function(e) {		
		
			e.preventRendering = true;			

			$(e.target).append('<div style="text-align:center"><img src="./img/loading_spinner.gif" /></div>');

			$.ajax({ 
				url: "./calendar_data_test.php", 
				success: function(dataSource) {  
					$(e.target).data('calendar').setDataSource(dataSource);
				} 
			});
			
		}
	});

Und hier der Inhalt meiner PHP-Datei, welche das JSON zurück geben soll (dann in Zukunft aus einer mySQL... aber erst wenns grundsätzlich klappt ;-) ...:

<?php
$out = array();

 for($i=1; $i<=15; $i++){     //from day 01 to day 15
    $data = date('Y-m-d', strtotime("+".$i." days"));
    $out[] = array(  
		'id' => $i,
        'name' => 'Event name '.$i,
		'location' => 'location',
        'startDate' => '2018-05-01',
        'endDate' => '2018-05-20'
    );
}

echo json_encode($out);
exit;
?>

Wie gesagt: Kein Fehler wird geworfen aber es gibt halt auch keine schönen Kalendereinträge 😕

Ich weiß nicht mal, ob das Datumsformat so passt welches das PHP zurück liefert. Der Kalender erwartet in Javascript ja ein "new Date(2018, 10, 17)".

Mein PHP liefert folgende Ausgabe (sieht für mich erst mal "gut" aus und der Browser rendert es auch korrekt als JSON):

[
 {
  id: 1,
  name: "Event name 1",
  location: "location",
  startDate: "2018-05-01",
  endDate: "2018-05-20"
 },
 {
  id: 2,
  name: "Event name 2",
  location: "location",
  startDate: "2018-05-01",
  endDate: "2018-05-20"
 },]

Freunde, ich bin über jede Hilfe extreeem dankbar!

Liebe Grüße! jup

PS: Der downloadbare Kalender-Code von www.bootstrap-year-calendar.com enthält das Event "yearChange" noch nicht. Ich habe mir die aktuelle Kaleder-Version von o.g. Github-Seite gezogen und diese hat das Event.

akzeptierte Antworten

  1. Hallo juppix,

    Der Kalender erwartet in Javascript ja ein "new Date(2018, 10, 17)".

    Ganz genau, und jQuery liefert es Dir erstmal als String.

    Auf der von Dir verlinkten GitHub Seite ist ein Beispiel, wie man das Problem durch Post-Processing lösen kann.

    Ich habe das gleiche Problem in einem aktuellen Web-Projekt in unserem Intranet, da habe ich es mit einem jQuery-Callback gelöst. Einfach weil ich das mal ausprobieren wollte...

    Was man definieren kann, ist ein eigener JSON-Decoder. Den "text json" Converter verwendet jQuery beim Empfang einer JSON Response, und defaultmäßig steckt dahinter einfach JSON.parse.

    In meiner Erweiterung auch, aber JSON.parse hat einen weiteren Parameter: Die Wiederbelebungsfunktion (reviver function). Diese Funktion wird für jedes Datenelement des vom JSON-String aufgespannten Objektbaumes aufgerufen, beginnend bei den Blättern bis hin zur Wurzel. Sie bekommt zwei Parameter: Name und Wert der wiederzubelebenden Objekt-Eigenschaft. Das ist nicht ganz einfach bei komplexen Objektbäumen, weil je nach Struktur der Name der Eigenschaft nicht reicht. In dem Fall muss man auf Post-Processing zurückfallen.

    Ich habe nicht geprüft, was performanter ist: Postprocessing oder eine Callback-Funktion, die pro Aufruf abfragen muss ob sie überhaupt aktiv werden muss. Vorteil des Callback mag sein, dass man hier keine Funktion bauen muss die den Objektbaum traversiert, sondern diese Aufgabe von JSON.parse abgenommen bekommt. In deinem Fall ist es einfach, weil Du ein Array of Objects vom Server bekommst, da musst Du nur sequenziell drüberlaufen und die beiden Date-Werte konvertieren.

      var jqTextToJson = {
              "text json": function(jsonString) {
                return JSON.parse(jsonString,
                    function(name, value) {
                        if (name === "startDate" || name === "endDate")
                            return new Date(value);
                        return value;
                    });
              }
          };
    
     $.ajax({
        dataType: "json",
        url: address,
        converters: jqTextToJson
     })
     .done(function (result) {
        // Ergebnis verarbeiten
     })
     .fail(function(xhr) {
        setErrorMessage("Fehler beim Laden: " + xhr.responseJSON);
     });
    

    Rolf

    --
    sumpsi - posui - clusi
    1. Du bist einfach klasse!

      10000 Dank ✌️

      Es funktioniert 😀 :

      yearChanged: function(e) {		
      		
      			e.preventRendering = true;			
      
      			$(e.target).append('<div style="text-align:center"><img src="./img/loading_spinner.gif" /></div>');
      
      			var jqTextToJson = {
      				  "text json": function(jsonString) {
      					return JSON.parse(jsonString,
      						function(name, value) {
      							if (name === "startDate" || name === "endDate")
      								return new Date(value);
      							return value;
      					});
      			    }
      			 };
      			
      			$.ajax({
      				dataType: "json",
      				url: "./calendar_data_test.php", 
      				converters: jqTextToJson,
      				success: function(dataSource) {  
      					$(e.target).data('calendar').setDataSource(dataSource);
      				} 			    
      			});		
      		}

      ... und die PHP (unverändert):

      <?php
      $out = array();
      
       for($i=1; $i<=15; $i++){     //from day 01 to day 15
          $data = date('Y-m-d', strtotime("+".$i." days"));
          $out[] = array(  
      		'id' => $i,
              'name' => 'Event name '.$i,
      		'location' => 'location',
              'startDate' => '2018-05-01',
              'endDate' => '2018-09-20'
          );
      }
      
      echo json_encode($out);
      exit;
      ?>
      
      1. Hallo juppix,

        für die Nachwelt habe ich das Thema Revive-Funktion auch mal im SelfWiki aufgegriffen, das war da bisher nur stiefmütterlich erklärt.

        Rolf

        --
        sumpsi - posui - clusi