Klaus1: Diagramm mit Chart.js zeigt nur Labels, keine Grafik

Hallo,

es ist sicherlich eine sehr spezielle Frage, aber ich hoffe, es findet sich hier jemand, der dennoch weiterhelfen kann.

In meinem Hauptfenster werden "Unterseiten" mittels object-Tag eingebunden. In einem dieser Unterseiten möchte ich eine Grafik mittels Chart.js anzeigen. Das hat wunderbar funktioniert, solange ich die Grafik-Werte etc. innerhalb der Unterseite ermittelt hatte. Jetzt soll aber der Anwender zwischen den Unterseiten wechseln können, ohne dass die Grafik-Werte dabei jedes Mal neu ermittelt werden müssen. Dafür habe ich die Variable "Grafikconfig" in der Hauptseite definiert und die Daten dort schon ermittelt. Beim ersten Aufruf der Grafik-Seite wird der Chart auch wunderbar dargestellt.

Wenn ich jetzt die Unterseite kurz wechsele, dann ändern sich die Werte für "Grafikconfig" nicht, aber der Chart wird beim 2. Aufruf nicht mehr angezeigt. Allerdings sieht man, dass die Labels weiterhin passen und dass auch beim MouseOver über die nicht angezeigte Grafik, das Info-Fenster mit dern korrekten Werten angezeigt wird. Die Werte sind also noch vorhanden und korrekt übergeben worden, dennoch wird die Grafik nicht sichtbar.

Die Daten habe ich sogar mal initial random erstellen lassen:

					laenge = Grafikconfig.data.labels.length;
					if (laenge < 100) {
						for (j=0; j<99-laenge+1; j++ ) {
							Grafikconfig.data.labels.push(" ");
							Grafikconfig.data.datasets.forEach(function(dataset) {
								dataset.data.push(zufallswerte());
							});
						}
					}

Der Aufruf bzw. das Erstellen der Grafik erfolgt über:

					var ctx = document.getElementById("canvas").getContext("2d");
					window.myLine = new Chart(ctx, parent.Grafikconfig);

Mit dem Debugger sehe ich, dass auch beim zweiten Aufruf das Objekt myLine noch "undefined" ist. Die Werte ändern sich auch nicht beim zweiten Aufruf. Ich kann zwischen dem ersten und dem zweiten Aufruf keinen Unterschied erkennen. Aber was ist der Unterschied? Irgendeinen wird es geben müssen, oder?

LG Klaus

  1. Tach!

    es ist sicherlich eine sehr spezielle Frage, aber ich hoffe, es findet sich hier jemand, der dennoch weiterhelfen kann.

    Ohne den Code zu sehen und ei Meldungen der Console ist eine Antwort nicht mehr als Spekulatius.

    Ich kann zwischen dem ersten und dem zweiten Aufruf keinen Unterschied erkennen. Aber was ist der Unterschied? Irgendeinen wird es geben müssen, oder?

    Vielleicht ein Reihenfolgenproblem. Vielleicht greifst du auf Dinge zu, die noch nicht geladen sind.

    dedlfix.

    1. Vielleicht ein Reihenfolgenproblem. Vielleicht greifst du auf Dinge zu, die noch nicht geladen sind.

      Naheliegend. Von daher würde ich das ganze Konzept mal überdenken. Wahrscheinlich funktioniert das auch nur zufällig. MFG

      1. Leider kann ich den Code nicht präsentieren, er ist ein wenig zu umfangreich um ihn hier zu posten.

        Von der Reihenfolge her: Die komplette Seite wird aufgerufen und es werden ca. 11 Reiter angezeigt. Bei diesem Aufruf werden die Grafik-Daten bereits ermittelt. Momentan erstmal nur Zufallswerte. Dann klicke ich auf den Reiter Grafik und die Grafik wird angezeigt. Danach klicke ich auf irgendeinen anderen Reiter und dessen Seite wird angezeigt. Nun wieder auf die Grafikseite. Die Daten haben sich nicht geändert, aber die Grafik wird nicht mehr angezeigt.

        Vom Ablauf her sehe ich keine Ursache, warum die Grafik nur beim ersten Mal angezeigt wird.

        Meine Vermutung ist, dass sich das Chart.js-Script beim Aufruf etwas speichert, was beim erneuten Aufruf dann stört.

        Mein nächster Versuch ist, dass beim Verlassen der Seite das Chart mit der Funktion destroy() bewusst wieder zerstört wird.

        Ich hatte nicht erhofft, dass jemand bereits die passende Lösung hat, aber vielleicht habt ihr eine Idee, wie ich das Problem eingrenzen könnte, was ich testen kann, um der Ursache auf die Spur zu kommen.

        LG Klaus

        1. Was mir gerade aufgefallen ist, vielleicht ist das ja die Ursache:

          Im Debugger erscheinen merkwürdigerweise alle aufgerufenen Seiten.

          Also von der Struktur her:

           mydomain.de
            	scripts
            	templates
            		grafik.php
            		info.php
          			seite1.php
          			seite2.php
          

          Ich hätte erwartet, dass hier immer nur die aktuell aufgerufene Seite zu sehen ist.

          Die Chart.js-Funktion destroy() beim beforeunload-event hatte keine Auswirkung.

          LG Klaus

          1. Tach!

            Im Debugger erscheinen merkwürdigerweise alle aufgerufenen Seiten.

            Definiere "erscheinen" und an welcher Stelle im Debugger genau.

            dedlfix.

            1. Im Debugger erscheinen merkwürdigerweise alle aufgerufenen Seiten.

              Definiere "erscheinen" und an welcher Stelle im Debugger genau.

              Im Entwicklerwerzeug des Firefox im Reiter Debugger werden auf der linken Seite die Quellen angezeigt. In der dort angezeigten Struktur erscheinen die aufgerufenen Seiten.

              Die angeklickte Seite wird wie folgt auf der Hauptseite eingebunden:

              function load_page(seite) {
              	main = document.getElementById("mainframe");
              	main.innerHTML = '<object id="contentobj" width="100%" height="100%" type="text/html" data="'+rootpfad+'/templates/'+seite+'" ></object>';
              }
              
              
              LG Klaus
              
              
              
              1. Tach!

                Im Entwicklerwerzeug des Firefox im Reiter Debugger werden auf der linken Seite die Quellen angezeigt. In der dort angezeigten Struktur erscheinen die aufgerufenen Seiten.

                Da ist alles zu finden, was geladen wird. Mitunter aber auch mehr oder eine andere Form. Beispielsweise kann statt einer eingebundenen minifizierten Datei das Original zu sehen sein, wenn es eine Map-Datei gibt, die der Browser erreichen kann und in der Zuordnungen definiert sind, was in der minifizierten Datei welchem Teil im Original entspricht. Hilft beim Debuggen, wenn man lesbaren Text präsentiert bekommt. Aber was da warum in deinem Fall zu sehen ist, kann ich nicht sagen.

                dedlfix.

              2. Hallo Klaus,

                	main.innerHTML = '<object id="contentobj" width="100%" height="100%" type="text/html" data="'+rootpfad+'/templates/'+seite+'" ></object>';
                

                nur eine Idee. Wenn du per innerHTML html-Elemente ersetzt, musst du auch die z.B. über getElementById erhaltenen Referenzen auf die ersetzten Objekte neu erstellen, auch wenn die neuen Objekte die gleiche ID haben, wie die alten.

                Hier ein Test.

                Gruß
                Jürgen

                1. nur eine Idee. Wenn du per innerHTML html-Elemente ersetzt, musst du auch die z.B. über getElementById erhaltenen Referenzen auf die ersetzten Objekte neu erstellen, auch wenn die neuen Objekte die gleiche ID haben, wie die alten.

                  Das mache ich fast schon zu oft, dass ich mir das Element immer wieder neu hole, obwohl ich die Referenz schon habe. Danke für den Tipp, aber das dürfte hier wahrscheinlich nicht die Ursache sein.

                  LG Klaus

        2. Tach!

          Dann klicke ich auf den Reiter Grafik und die Grafik wird angezeigt.

          Zum Beispiel hier musst du etwas genauer hinschauen. Passiert das synchron oder wird das nur angestoßen und der Browser lädt etwas im Hintergrund, während du weitermachst? Du müsstest dabei sicherstellen, dass du auf das Bin-fertig-Event wartest, bevor du Dinge machst, die sich auf das zu ladende beziehen.

          Das muss an dieser Stelle nicht unbedingt ein Problem sein, wie das geschilderte. Ich hab das nur mal exemplarisch herangezogen. Aber sowas kann prinzipiell an allen Stellen auftreten, wo asynchrone Dinge passieren. Sowas passt dann rein zufällig in bestimmten Situationen zeitlich zueinander und in anderen nicht mehr.

          Ich hatte nicht erhofft, dass jemand bereits die passende Lösung hat, aber vielleicht habt ihr eine Idee, wie ich das Problem eingrenzen könnte, was ich testen kann, um der Ursache auf die Spur zu kommen.

          Naja, solange man keinen konkreten Verdacht hat, kann man erstmal nur die allgemeinen Maßnahmen ausführen: mit Kontrollausgaben die erwarteten Werte und auch den Ablauf kontrollieren.

          dedlfix.

          1. Du müsstest dabei sicherstellen, dass du auf das Bin-fertig-Event wartest, bevor du Dinge machst, die sich auf das zu ladende beziehen.

            Die Grafik wird erst erstellt, wenn die Seite geladen wurde:

            Das parent-Objekt verwende ich, da die Veriable ja im Hauptdokument definiert wird.

            
            window.onload = function() {
            			var ctx = document.getElementById("canvas").getContext("2d");
            			window.myLine = new Chart(ctx, parent.Grafikconfig);
            };
            
            
            1. Tach!

              Das parent-Objekt verwende ich, da die Veriable ja im Hauptdokument definiert wird.

              
              window.onload = function() {
              			var ctx = document.getElementById("canvas").getContext("2d");
              			window.myLine = new Chart(ctx, parent.Grafikconfig);
              };
              
              

              Vielleicht wird der Eventhandler nicht mehr aufgerufen. Setz eine Kontrollausgabe rein, wie console.log('window.onload called');.

              dedlfix.

              1. Vielleicht wird der Eventhandler nicht mehr aufgerufen. Setz eine Kontrollausgabe rein, wie console.log('window.onload called');.

                Er wird aufgerufen. Hatte mir da einen Breakpoint gesetzt, um zu sehen, ob das Objekt vielleicht immernoch existiert und daher das Problem auftritt.

                Andernfalls würde die Grafik (das Diagramm) auch gar nicht erst mehr angezeigt werden.

                Die Grafik wird ja theoretisch auch erzeugt, nur eben nicht sichtbar, denn beim MouseOver über Werte der nicht sichtbaren Kurve wird das Popup mit den Zahlenwerten.

                Theoretisch würde ich erwarten, dass beim Neuladen der Seite, der gesamte Inhalt und die Aktionen dieser Seite vergessen werden. Habe ich denn eine Möglichkeit den Zustand eines Objekts mit allem drum und dran zu speichern und mit einem anderen Objekt inhaltlich zu vergleichen? Vielleicht wird etwas inhaltlich an meiner Variable "Grafikconfig" geändert, das einen erneuten Aufruf dann verbaut?

                LG Klaus

                1. Tach!

                  Vielleicht wird der Eventhandler nicht mehr aufgerufen. Setz eine Kontrollausgabe rein, wie console.log('window.onload called');.

                  Er wird aufgerufen. Hatte mir da einen Breakpoint gesetzt, um zu sehen, ob das Objekt vielleicht immernoch existiert und daher das Problem auftritt.

                  Was ich meinte ist: muss der für jede Grafik erneut aufgerufen werden, und wenn ja, passiert das auch?

                  Habe ich denn eine Möglichkeit den Zustand eines Objekts mit allem drum und dran zu speichern und mit einem anderen Objekt inhaltlich zu vergleichen?

                  Das hört sich jetzt nach AB-Problem an. Du versucht A zu lösen und fragst nach B, weil du das für die Lösung hältst, aber eigentlich gar nicht weißt, ob das A löst.

                  Kannst du ein ganz minimalistisches Beispiel erstellen, wo das Problem zutage tritt? Manchmal stellt sich dabei auch heraus, dass das korrekt läuft. Dann hat man ein Problem in einer der nebensächlichen Bedingungen. Auf alle Fälle hat man mit dem Minimalbeispiel ein gutes Testobjekt.

                  dedlfix.

                  1. Ich hab es (endlich) gelöst bekommen.

                    Ich wollte beim Verlassen der Seite die Chart.js-Funktion destroy() aufrufen. Aber beim Aufruf eines Reiters wird ja nur der innerHTML eines Div-Tags neu geschrieben. Damit fand kein "beforeunload"-event statt.

                    Ich habe dann das Neuladen der Seite angepasst und nur wenn man von der Grafik-Seite kommt, dann wird destroy() aufgerufen. Offenbar wird mit dem Destroy etwas zurückgesetzt, was er sich ansonsten irgendwo gemerkt hat und damit den erneuten Aufruf verwehrte.

                    Jetzt funktioniert alles und ich bedanke mich ganz herzlich für die Geduld und Unterstützung.

                    Yeah!

                    LG Klaus