Peter: Es soll eine js-Variable an ein html-Input-Feld als Vorbelegung übergeben werden.

problematische Seite

Hallo liebe HTML- und js - Spezialisten.

Ich möchte auf einer html-Seite für einen input-Tag einen Wert vorbelegen. Im Bereich <head> ermittle ich mit javascript das Datum, welches ich vorbelegen möchte. (Aktuelles Datum - 1 Tag) Mein Problem ist, wie bekomme ich die js-Variable dem html-input-value zugegwiesen.

Anbei mein html-Seitencode:

<!DOCTYPE html>
<html lang="de">
 <head>
  <meta charset="utf-8">
  <title>Google Chart parametriert durch flask</title>
  <style>
   div linechart_material { height: 20em; }
   form                   { margin-bottom: 2em; } 
  </style>
  <script src="https://www.gstatic.com/charts/loader.js"></script>
  <script>
/*  
  Funktion um Tage von einem Datum abzuziehen oder zu addieren
  days kann deshalb positiv oder negativ sein
*/
  function addDaysToDate(date, days){
        var res = new Date(date);
        res.setDate(res.getDate() + days);
        return res;
      }
  let days_2_sub = -1;
  let date_act = '',
      date_start = '';
  
  date_act = new Date();    
  date_start = addDaysToDate(date_act, days_2_sub)
  **date_start** = date_start.toISOString().split('T')[0];

  </script
 </head>
    <body>
       <label for="date">Von :</label>
       <input type="date" name="day_from" value=**`<script type="text/javascript">document.write(date_start);</script>`** />
       <label for="time">Von :</label>
       <input type="time" name="time_from" value="00:00:00" /><br>
    </body>
</html>

Also, es soll der Inhalt der js-Variablen date_start, sie hat das Format jjjj-mm-tt dem value von <input type="date" name="day_from" value= zugewiesen werden. Hardgecoded mit value="2023-03-11" funktioniert die Vorbelegung.

Hat jemand das Wissen oder eine Idee?

Vielen Dank schon Mal😊

  1. problematische Seite

    @@Peter

    Im Bereich <head> ermittle ich mit javascript das Datum, welches ich vorbelegen möchte.

    Das ist nicht gut, weil es das Rendern der Seite verzögert. Scripte sind am Ende des body gut aufgehoben.

    Anbei mein html-Seitencode:

        <body>
           <label for="date">Von :</label>
           <input type="date" name="day_from" value=**`<script type="text/javascript">document.write(date_start);</script>`** />
           <label for="time">Von :</label>
           <input type="time" name="time_from" value="00:00:00" /><br>
        </body>
    

    Die Eingabefelder sind nicht in einem Formular? Warum nicht?

    Und sie haben keine zugeordnete Beschriftung. Die Angabe im for-Attribut des label-Elements bezieht sich auf eine gleichnamige ID. Solche fehlen bei dir.

    Und zweimal „Von“ ist auch keine aussagekräftige Beschriftung. Da müsste schon „Datum“ bzw. „Uhrzeit“ mit dabeistehen.

    Sinnvoll wäre wohl eine Gruppierung in einem fieldset mit legend:

    <fieldset>
      <legend>Startzeitpunkt</legend>
      <label for="date">Datum</label>
      <input id="date type="date" name="day_from"/>
      <label for="time">Uhrzeit</label>
      <input id="time type="time" name="time_from" value="00:00:00"/>
    </fieldset>
    

    Mein Problem ist, wie bekomme ich die js-Variable dem html-input-value zugegwiesen.

    Du musst dir das Eingebefeld im DOM raussuchen:

    const dateInputElement = document.querySelector('[name="day_from"]');
    

    oder – wenn das Element jetzt eine ID hat:

    const dateInputElement = document.querySelector('#date');
    

    Wenn das Eingabefeld in einem Formular wäre, müsste nicht erst gesucht werden; dann wäre es schon als document.forms.<Name des Formulars>.elements.day_from verfügbar.

    Dem Element weist du den Wert als value-Eigenschaft zu:

    dateInputElement.value = date_start;
    

    🖖 Живіть довго і процвітайте

    --
    „Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“
    — @Grantscheam auf Twitter
    1. problematische Seite

      Hallo Gunnar,

      dateInputElement.value = date_start;
      

      Bis auf diese Zeile 100% Zustimmung. Zum Thema valueAsDate siehe meinen Beitrag.

      Rolf

      --
      sumpsi - posui - obstruxi
    2. problematische Seite

      Hallo Rolf, hallo Gunnar, vielen Dank für die schnelle Antwort und vor Allem auch für die umfassende Begründung und weiterführende Tips, ganz toll von Euch !! Werde es heute Abend gleich umsetzen. Eigentlich bin ich das erste Mal mit HTML und Javascript in Berührung gekommen, als ich mit einem Raspi und einem Sensor Daten aufgezeichnet und in einer DB gespeichert habe und nun die Daten eben auch noch im Browser visualisieren möchte. Da nur für den internen Gebrauch, dachte ich das geht mal so kurz .....

      Werde mich nun doch auch mit HTML und JS näher beschäftigen!

      Nochmals vielen Dank 👍

      Peter

  2. problematische Seite

    Hallo Peter,

    <script>...</script> ist ein HTML Element. Ein solches kann nicht innerhalb eines Attributs eines anderen Elements (das input-Element) notiert werden. Wenn überhaupt, müsste dein script-Snippet das komplette HTML für das input-Element generieren.

    Das ist aber nicht die beste Idee.

    Besser ist es, mit Mitteln der DOM Programmierschnittstelle das input-Element herauszusuchen und ihm dann den gewünschten Wert zuzuweisen. Dafür gilt es mehreres zu beachten. Das mag jetzt kompliziert klingen, aber es sind die Grundlagen der Script-Organisation und des DOM Zugriffs, die hier benötigt werden.

    (1) Dein Script steht im head, wird also ausgeführt, wenn das DOM noch gar nicht aufgebaut ist. Ohne weiteres kannst Du aus diesem Script heraus also nicht auf ein input-Element zugreifen, das im body steht. Es gibt mehrere Ansätze, wie man das lösen kann

    • Verschiebe das Script an das Ende des body
    • Packe deinen Initialisierungscode in einen DOMContentLoaded Eventhandler. Unser Wiki-Artikel Ereignisverarbeitung enthält einige Beispiele dazu.
    • Gib dem Script das Attribut defer, dadurch wird es erst gestartet, wenn der Body fertig eingelesen ist. Das geht aber nur bei Scripten, deren Quelltext über ein src-Attribut von extern geladen wird.
    • Mach aus dem Script ein Modul (type="module"). Dadurch gelten im Script leicht andere Regeln, aber type="module" bringt die defer-Eigenschaft mit und das Script wird erst ausgeführt, wenn das DOM aufgebaut ist.

    Der DOMContentLoaded Handler ist sozusagen die traditionelle Lösung. Aber die Lösungen 1, 3 und 4 sind deutlich einfacher.

    (2) Um das input-Element zu finden, könnstest Du die Methode document.getElementsByName() verwenden. Das ist ein bisschen umständlich, weil das name-Attribut im DOM nicht eindeutig sein muss und Du deshalb von getElementsByName - wie der Name sagt - Elemente zurückbekommst und das erste Element der Liste erstmal herausholen musst.

    Einfacher ist es, dem gewünschten Element eine ID zu geben - die muss eindeutig im DOM sein - und mit getElementById zuzugreifen.

    Alternativ kannst Du auch document.querySelector("[name=date_from]") verwenden, also einen Attribut-Selektor benutzen. Damit bekommst Du das erste Element mit diesem Namen. Das setzt deinerseits die Disziplin voraus, dass der Name eindeutig ist.

    (3) Um einem <input type="date"> Element ein Datum zuzuweisen, kann man dem Value eine passende Zeichenkette zuweisen. Diese muss dann entweder im lokalen Format sein (z.B. tt.mm.jjjj) oder im ISO-Format jjjj-mm-dd.

    Einfacher ist die Verwendung der Eigenschaft valueAsDate - der weist Du nämlich einfach das Date-Objekt zu.

    <head>
       ...
       <script type="module">
          const heute = new Date(),
          const gestern = new Date(heute.getYear(),
                                   heute.getMonth(),
                                   heute.getDate() - 1);
    
          const datumVon = document.getElementById("day_from");
          datumVon.valueAsDate = gestern;
    
          // Die beiden letzten Zeilen könnte man auch zu einer zusammenfassen:
          document.getElementById("day_from").valueAsDate = gestern;
    
       </script>
       ...
    </head>
    <body>
       ...
       <input type="date" id="day_from" name="day_from">
       ...
    </body>
    

    Das input-Element braucht die ID für den JavaScript-Zugriff und das name-Attribut, um als Form-Element zum Server geschickt werden zu können.

    Ein Hinweis am Rande:

      let date_act = '',
          date_start = '';
    
      date_act = new Date();
      date_start = ...;
    

    Es ist nicht sinnvoll eine Variable mit irgendeinem Wert zu initialisieren, wenn man ihr gleich danach einen anderen Wert zuweist. Da kann mann sich auch gleich mit dem richtigen Wert initialisieren, so wie ich das in meinem Vorschlag getan habe.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. problematische Seite

      @@Rolf B

      (3) Um einem <input type="date"> Element ein Datum zuzuweisen, kann man dem Value eine passende Zeichenkette zuweisen. Diese muss dann entweder im lokalen Format sein (z.B. tt.mm.jjjj) oder im ISO-Format jjjj-mm-dd.

      Nein, das stimmt nicht. Wo hast du das denn her? In der Spec kann ich nichts dergleichen finden.

      Dort ist beschrieben, was ein valid-date-string ist. '2023-03-13' ist einer, '13.03.2013' ist keiner.

      Dort steht auch, wie für Datum-Eingabefelder der value sanitization algorithm aussieht: “If the value of the element is not a valid date string, then set it to the empty string instead.”

      Und genauso verhalten sich auch Firefox, Safari und Chromia. Test

      🖖 Живіть довго і процвітайте

      --
      „Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“
      — @Grantscheam auf Twitter
      1. problematische Seite

        Hallo Gunnar,

        Wo hast du das denn her?

        Ich muss gestern wohl besoffen gewesen sein. Ich bin überzeugt, ich hätte das ausprobiert und es hätte funktioniert. Heute dagegen geht's nicht.

        Also, ja, value muss YYYY-MM-DD bekommen. Oder YYYYY-MM-DD. Oder YYYYYY-MM-DD. Die Spec begrenzt es nicht, aber Chrome macht bei 275760-09-13 02:00:00 Schluss. Was einem Wert des Date-Objekts von 8'640'000'000'000'000ms entspricht. Oder der Sekundenzahl von 100 Millionen Tagen (ohne Schaltsekunden).

        Strange…

        Rolf

        --
        sumpsi - posui - obstruxi
        1. problematische Seite

          Hi,

          Also, ja, value muss YYYY-MM-DD bekommen. Oder YYYYY-MM-DD. Oder YYYYYY-MM-DD. Die Spec begrenzt es nicht, aber Chrome macht bei 275760-09-13 02:00:00 Schluss. Was einem Wert des Date-Objekts von 8'640'000'000'000'000ms entspricht. Oder der Sekundenzahl von 100 Millionen Tagen (ohne Schaltsekunden).

          da kann ich nur hoffen, daß mich das nicht so ereilt wie damals das Jahr-2000-Problem - da mußte ich einiges an Code anpassen.

          Evtl. wird das Renteneintrittsalter nicht so stark erhöht, daß mich das dann doch noch trifft … 😉

          Ist ja schon in ca. 273 Jahrtausenden …

          cu,
          Andreas a/k/a MudGuard

    2. problematische Seite

      Hallo Rolf,

      ich hoffe es ist ok für Dich wenn ich mich nochmal zu meinem Problem direkt bei Dir melde.

      Also, habe Deinen Vorschlag heute umgesetzt. Heite ist der 14.03.2023 Beim debuggen in Chrome wird für gestern = Mo, 13.03.2023 angezeigt, aber in meinem <input type="date" id="day_from" name="day_from" /> wird als Vorbelegung der 12.03.2023 ausgegeben.

      Das kann doch nicht sein!!!!

      Anbei mein html-Code:

      <!DOCTYPE html>
      <html lang="de">
       <head>
        <meta charset="utf-8">
        <title>Google Chart parametriert durch flask</title>
        <style>
         div linechart_material { height: 20em; }
         form                   { margin-bottom: 2em; } 
        </style>
        <script src="https://www.gstatic.com/charts/loader.js"></script>
        <script type="module">
      /*  
        Funktion um Tage von einem Datum abzuziehen oder zu addieren
        days kann deshalb positiv oder negativ sein
      */
      
            const heute = new Date();
      //      let jahr = heute.getFullYear();
      //      let monat = (heute.getMonth() + 1);
      //      let tag = (heute.getDate() - 1);
            
            let gestern = new Date(heute.getFullYear(),
                                   heute.getMonth(),
                                   heute.getDate() - 1);
      
      
                                   
            document.getElementById("day_from").valueAsDate = gestern;
      
        </script>
       </head>
          <body>
             <label for="date">Von :</label>
             <input type="date" id="day_from" name="day_from" />
             <label for="time">Von :</label>
             <input type="time" id="time_from" name="time_from" value="00:00:00" /><br>
          </body>
      </html>
      
      

      Kannst Du mir einen Tipp geben?

      Danke schon mal.

      Peter

      1. problematische Seite

        Hallo Peter,

        ich weiß, woran es liegt - aber ich überlege gerade noch an einer Lösung.

        Problem ist, dass das Date-Objekt seine Informationen als UTC-Zeit speichert. Wenn Du ein Date-Objekt mit "2023-03-13" erzeugst, dann ist das in Wahrheit "2023-03-13 00:00:00.000" lokaler Zeit und "2023-03-12 23:00:00.000" UTC Zeit. Sobald die Sommerzeit losgeht, ist es sogar "2023-03-12 22:00:00.000" UTC.

        Das input-Element übernimmt nicht das Datum der lokalen Zeit, sondern das Datum der UTC Zeit. Was doof ist.

        Ich muss jetzt gucken, wie Du ein Datum als UTC-Datum erzeugst. Für Deutschland dürfte es am einfachsten sein, das Date-Objekt mit Uhrzeit 12:00:00 zu erzeugen.

        let gestern = new Date(heute.getFullYear(),
                                     heute.getMonth(),
                                     heute.getDate() - 1,
                                     12, 0, 0);
        

        Diese Lösung ist nicht für alle Länder tragfähig, aber in D schon.

        Ich habe gerade noch bei Stackoverflow einen interessanten Hack gefunden: Schwedisches Datum!

        let gestern = new Date(heute.getFullYear(),
                                     heute.getMonth(),
                                     heute.getDate() - 1)
        console.log(gestern.toLocaleString("sv").substring(0,10));
        // Ausgabe am 14.03.2023: "2023-03-13 00:00:00"
        

        Das schwedische Datumsformat ist YYYY-MM-DD, also ISO-ähnlich. d.h. auf diese Weise bekommst Du einen ISO Datumsstring ohne Timezone-Verfälschung. Den kannst Du dann dem value des input-Elements zuweisen.

        inputElement.value = gestern.toLocaleString("sv").substring(0,10);
        

        Schön ist anders, aber funktioniert 😀

        Rolf

        --
        sumpsi - posui - obstruxi
        1. problematische Seite

          Hallo Rolf, ganz lieben Dank für die schnelle Antwort👍

          Wäre ich nie draufgekommen😏