Ramazan : Fragen zur Vorführaufgabe / Daten an Local Storage übergeben

Ersteinmal paar Screens zum schnelleren Verständnis der Aufgabenstellung

Eine Tabelle mit einer Suchfunktion und Kontaktbearbeiten (bei klick des Plus Buttons)

Eigentliche Aufgabenstellung



Problem:

(Abbildung 4) Wir haben es hinbekommen das wenn man was eintippt in die Formulare, er erst prüft ob alle Felder korrekt sind, und dann erst auf Abbildung 3 übergeht. Unser Problem ist: eingetragene Daten übernimmt er nicht in die Tabelle, also ins Locale storage....

  1. Hey,

    Unser Problem ist: eingetragene Daten übernimmt er nicht in die Tabelle, also ins Locale storage....

    Unser Problem ist: Was habt ihr gemacht?

    Gruß
    Jo

  2. Ersteinmal paar Screens zum schnelleren Verständnis der Aufgabenstellung

    Eine Tabelle mit einer Suchfunktion und Kontaktbearbeiten (bei klick des Plus Buttons)

    Eigentliche Aufgabenstellung



    Problem:

    (Abbildung 4) Wir haben es hinbekommen das wenn man was eintippt in die Formulare, er erst prüft ob alle Felder korrekt sind, und dann erst auf Abbildung 3 übergeht. Er übergibt die Daten dann auch in die Tabelle (abb 3), also ins Locale Storage. Problem: sobald man einen kontakt angelegt hat hat man in der Spalte aktion 2 Optionen: 1. die vorhandene Tabellenzeile bearbeiten, und aktualiesiert wieder übergeben. Bei uns erstellt er eine neue Tabellenzeile mit den umgeänderten Daten, und das soll er vermeiden in dem er durch die vergebene id weiß ob es ein neues kontakt ist oder ein vorhandenes

  3. HTTPParameter und localStorage? Das passt nicht zusammen. Der Auftraggeber mächt bitte präzisieren wo er die Daten gspeichert haben will, serverseitig oder clientseitig?

    1. Hallo pl,

      clientseitig ist klar gesagt. Und JavaScript kann die URL analysieren - rein technisch kein Problem also.

      Best Practice ist es aber nicht, man würde normalerweise den Hash-Teil der URL verwenden.

      Rolf

      --
      sumpsi - posui - clusi
      1. clientseitig ist klar gesagt. Und JavaScript kann die URL analysieren - rein technisch kein Problem also.

        Für eine clientseitige Speicherung ist die URL völlig irrrelevant!

        1. Hallo pl,

          den Query-Teil der URL kannst Du in JavaScript auswerten, wenn Du Bock drauf hast. Wie gesagt, es ist kein Best Practice, darum wird der Bock auch meckern. Aber gehen tut's schon.

          Ruf mal auf: https://wiki.selfhtml.org/wiki/JavaScript/Web_Storage?foo=3

          Und dann öffne die Entwicklerwerkzeuge und lass Dir location.search ausgeben. Das kann man nutzen, um dann im clientseiten JavaScript aus dem LocalStorage den Eintrag mit ID 3 herauszulesen.

          Besser wäre für eine SPA-artig Seite natürlich http://example.org/foo/storage.html#foo=3

          Rolf

          --
          sumpsi - posui - clusi
  4. @@Ramazan

    … im JavaScript-Tutorial von W3C auf der Seite https://w3schools…

    Du solltest die Schule wechseln.

    (Das W3C und W3Schools haben – außer das beide Namen mit W3 anfangen – nichts miteinander zu tun.)

    LLAP 🖖

    --
    „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
    1. Wahrscheinlich sollen die Schüler vorgeführt werden.

      Daten übernimmt er nicht in die Tabelle, also ins Locale storage..

      Logisch!

      Zusammenwirken von Dateien

      Genauso blödsinnig.

      1. Hallo Gunnar und pl,

        (ui, hätte nie gedacht euch zwei mal in einem Atemzug zu erwähnen)

        blödsinnig ist euer Bashing von W3Schools und Lehrer, das hilft Ramazan um 0.0 Bits weiter.

        Ihr hättet zumindest Alternativen benennen können:

        SelfWiki: https://wiki.selfhtml.org/wiki/JavaScript/Web_Storage#localStorage

        MDN: https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage

        Ob diese beiden Quellen allerdings besser sind, habe ich jetzt nicht studiert. Und - Ramazan - wenn Du mehr Hilfe brauchst, brauchen wir Code.

        Rolf

        --
        sumpsi - posui - clusi
        1. Nun, Eine Tabelle ist eine Möglichkeit Daten darzustellen. localStorage hingegen ist eine Möglichkeit Daten zu speichern aber noch lange keine Tabelle!

          In der Aufgabenstellung ist von ID die Rede. Das ist üblich um Datensätze eindeutig zu kennzeichnen. Natürlich kann man eine neue ID per HTTP Request anfordern, sofern eine Solche serverseitig erzeugt werden soll.

          Und natürlich kann man per ID einen ganzen Datensatz per HTTP anfordern. Insgesamt muss man sogar die ganze Programmierlogik über HTTP Parameter abbilden bei einer Client Server Architektur!

          Die Frage ist jedoch, welche Rolle localStore hierbei spielen soll!

          nd ja, localStorage speichert keine Tabellen sondern Schlüssel-Werte-Paare.

          .

          1. Hallo pl,

            du kannst auch ein JavaScript Array nehmen, es mit JSON zum String flachklopfen und im localStorage ablegen. So steht es doch in der Aufgabe: Ein Kontakte-Array wird gelesen, bei Bedarf geupdated und wieder geschrieben. Die ID ist ein Index / ein Key in diesem Array. Wo ist das Problem?

            Rolf

            --
            sumpsi - posui - clusi
            1. Natürlich kann man auch fortlaufende Nummern (IDs) local verwalten. Und wenn die Datenstruktur so aussieht: [{},{}..] könnte man sogar den ersten Block {id: 123} dazu verwenden. Was die Konsistenz der Daten sicherstellt.

              PS: Die gezeigte Datenstruktur ist in Template-Engines üblich. U.a. auch in Mustache.

              1. Wobei: Für eine direkte Adressierung über ID ist ein Array ungeeignet.

                1. Hallo pl,

                  ja, dafür macht man besser ein Objekt mit numerischen Propertynames.

                  Oder man pfeift auf direkte Adressierung und arbeitet sequenziell: Mit kontakte.find(k => k.id==suchId) kommt man auch an den gewünschten Eintrag heran. Selbst bei einer Million Kontakten in der Liste ist ein .find auf eine nicht existierende ID in einem Wimpernschlag durch (gerade in der Konsole getestet).

                  Die Suche nach einer freien ID kann man durch eine Maximumsuche lösen, eine gelöschte ID sollte eh nicht wiederverwendet werden. Alles in einem Wimpernschlag erledigt.

                  Die JSON Serialisierung und Deserialisierung ist hier eher der Zeitfaktor. JSON.stringify dauert 500ms, parse sogar 1000ms. Eine Million Kontakte ist definitiv nicht zu empfehlen 😂

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. Die Suche nach einer freien ID kann man durch eine Maximumsuche lösen

                    Das kann zu Datenverlust führen. Nämlich dann, wenn das Maximum gleich einer ID ist die bereits vergeben ist. Besser also eine von der Anzahl der Records unabhängige Verwaltung fortlaufender Nummern. Alles zusammen:

                    {
                       cfg: {lfdnr:2},
                       1:{name:'',vname:'',id:1},
                       2:{name:'',vname:'',id:2,phone:''}
                    }
                    

                    .

                    1. Hallo pl,

                      das Maximum ist immer gleich einer vergebenen ID. Nämlich der maximalen.

                      Das erforderliche +1 auf's Maximum war mir jetzt so selbstverständlich, dass ich es unterschlagen habe. Hätte ich für eine Schülerfrage nicht tun sollen.

                      Datenverlust gibt's aber trotzdem, nämlich beim Überlauf der Mantisse eines Number-Objekts (gerade probiert, 2**52+1 != 2**52 ist noch true, 2**53+1 != 2**53 nicht mehr). Da sind wir im Sextillionenbereich, bis dahin muss auch ein dicker Xeon viel Popcorn rösten und der Lehrer ist in Rente. Problem gelöst.

                      Dein separater Eintrag mit der maximalen ID löst es natürlich auch. Solange keiner vergisst, die ID zu aktualisieren 😉 - was sich durch Kapselung des Kontaktarrays in ein Objekt durch Unittests gut ausschließen lässt.

                      Rolf

                      --
                      sumpsi - posui - clusi
                      1. @Rolf B

                        das Maximum ist immer gleich einer vergebenen ID. Nämlich der maximalen.

                        Achso. Ist ja noch umständlicher. Warum sträubst Du dich so vehement gegen eine eigene Verwaltung fortlaufender Nummern? Das ist doch nun wirklich das Naheliegendste!

                        Dein separater Eintrag mit der maximalen ID löst es natürlich auch.

                        Nicht separat: Sondern zusammen mit den Daten!

                        Solange keiner vergisst, die ID zu aktualisieren 😉 - was sich durch Kapselung des Kontaktarrays in ein Objekt durch Unittests gut ausschließen lässt.

                        Unittest ist das falsche Buzzwort. Die Kapselung erledigt eine Funktion freeze_thaw() die sowohl die Serialisierung (JSON) als auch das Hochzählen der ID erledigt.

                        Das Zauberwort heißt also Data Access Layer und die Funktion ist die Schnittstelle. Wenn in der nächsten Übung die Daten nämlich auf Diskette gespeichert werden sollen, ist das ziemlich flott erledigt: Da ist nur die Schnittstelle anders die Daten sind dieselben.

                        MfG

                        1. Hallo,

                          Wenn in der nächsten Übung die Daten nämlich auf Diskette gespeichert werden sollen,

                          Diskette? Wasndas?

                          Oder anders gefragt: Von wannen seid Ihr?

                          Gruß
                          Kalk

                          1. @@Tabellenkalk

                            Diskette? Wasndas?

                            So’n neumodisches Zeugs, was Hotti jetzt anstatt Lochkarten einsetzt.

                            Ja so isser, unser Hotti, immer seiner Zeit ein Stück voraus.

                            LLAP 🖖

                            --
                            „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
                            1. Ich kann doch meine Bandlaufwerke nennen wie ich will.

                              Demo

                        2. Hallo pl,

                          Das ist doch nun wirklich das Naheliegendste!

                          Es gibt immer zwei Wege. Der eine spart Speicher und braucht mehr Laufzeit, der andere ist schneller und braucht mehr Speicher. Ein separater Eintrag im Array (ja, separat. Und natürlich zusammen mit den Daten im gleichen Array) für die maximale ID setzt jedenfalls voraus, dass man ihn nicht irrtümlich als Nutzdaten verarbeitet.

                          Unittest ist das falsche Buzzwort.

                          Das ist kein Buzzwort, das ich da blase, sondern eine Voraussetzung dafür, dass man seinem DAL vertrauen kann. Egal welche Implementierung es ist.

                          Rolf

                          --
                          sumpsi - posui - clusi
                      2. @Rolf B

                        hier mal eine Demo mit Erläuterungen. Schau Dir mal an, wie der Data Access Layer implementiert ist:

                        Die Funktionen freeze() und thaw() referenzieren die Schnittstelle, also die Funktion freeze_thaw(). Während freeze(stash) die zu speichernde Datenstruktur in stash übergeben bekommt, liefert thaw() selbige aus dem Datenspeicher zurück.

                        Die Schnittstelle zum DAL ist also nur eine Funktion und der Code arbeitet mit Referenzen auf diese Funktion. Zu einem etwaigen Austausch des DAL wäre also nur die Referenzierung abzuändern.

                        MfG

                        1. Hallo pl,

                          nope, nicht einverstanden.

                          1. freeze und thaw wären besser getrennte Funktionen geblieben. Das Mapping auf freeze_thaw bringt aus meiner Sicht keinen Nutzen.
                          2. warum setzt thaw einen Defaultwert in den stash wenn der localstorage leer ist? Ich sehe es mal als Testhilfe an…
                          3. warum ist das Management des stash und das Mapping auf's UI in einem Layer vereint? Du vermischst hier Model und View.

                          Eine Alternativ-Implementierung habe ich nicht in der Schublade, mal gucken wie ich heute dazu kommen.

                          Rolf

                          --
                          sumpsi - posui - clusi
                          1. @Rolf B

                            1. freeze und thaw wären besser getrennte Funktionen geblieben. Das Mapping auf freeze_thaw bringt aus meiner Sicht keinen Nutzen.

                            Es bringt den Nutzen, daß es genau eine Funktion ist. Und dadurch daß diese eine Funkion nur referenziert ist, ist die ganze Schnittstelle einfach austauschbar:

                            var freeze = local ? freeze_thaw : ajax;
                            var thaw   = local ? freeze_thaw : ajax;
                            

                            Der Rest vom Code bleibt von einem Austausch des DAL unberührt. Im CODE sind es übrigens 2 Funktionen, so besser lesbar.

                            1. warum setzt thaw einen Defaultwert in den stash wenn der localstorage leer ist?

                            Weil ein Defaultwert gesetzt werden muss. Ansonsten wirft window.JSON.parse() eine Exception.

                            Ich sehe es mal als Testhilfe an…

                            Natürlich kannst Du auch mit Exceptions arbeiten wenn Dir das lieber ist. Das liegt in Deinem Ermessen. Ich persönlich halte es jedoch für unzweckmäßig es an dieser Stelle auf eine Exception ankommen zu lassen: Wo ein Default genügt! Wobei lfdnr ohnehin vorbelegt werden muss!

                            1. warum ist das Management des stash und das Mapping auf's UI in einem Layer vereint? Du vermischst hier Model und View.

                            UI und Programmlogik sind per Template doch klar voneinander getrennt!

                            .

                            1. Hallo pl,

                              Es bringt den Nutzen, daß es genau eine Funktion ist.

                              Okay, sehe ich in dieser kompakten Vorstellung ein. Aber für den praktischen Einsatz wäre hier ein (austauschbares) Objekt vorzuziehen, oder findest Du nicht?

                              Defaultwert

                              Da verstehen wir uns miss. Eine Exception kann auftreten wenn jemand den localStorage-Eintrag vandalisiert, so dass kein gültiger JSON-String mehr drin steht. Dagegen bietet dein Code keinen Schutz. Ein fehlender localStorage-Eintrag liefert null und ein JSON.parse(null) gibt sauber null zurück. Dagegen gehst Du korrekt mit dem || Teil an. Mein Einwand galt aber Herrn D. Ummie. Mein Default wäre { lfdnr: 0, names: [] } gewesen.

                              UI und Programmlogik

                              Ich rede nur von der Programmlogik. Die ist auch zu layern, in Model (Daten), View (Mapping Model-DOM) und Controller. Bei einem kleinen Demoprogramm kommt's nicht drauf an, bei großen Systemen ist es unverzichtbar. Aber Du willst das Thema DAL präsentieren, und dann solltest Du auch genauer zeigen wie das Layering erfolgt.

                              Rolf

                              --
                              sumpsi - posui - clusi
                              1. Guck bitte in den Quelltext dann siehst Du das Template. Die Renterfunktion heißt übrigens xr(). Und nein, warum die nicht render() heißt machen wir hier nicht zum Thema!

                  2. problematische Seite

                    @Rolf B

                    auf eine ID kann man tatsächlich verzichten. Zum Selektieren eines Eintrags im DO genügt der Index eines Array [{},{}..], mit einer solchen Datenstruktur kann auch jede Templatingengine umgehen.

                    MfG

        2. @@Rolf B

          blödsinnig ist euer Bashing von W3Schools und Lehrer

          Niemand hat hier W3Schools-Bashing betrieben. Falls du es missverstanden hast: in „Du solltest die Schule wechseln“ war die Schule von Ramazan gemeint, nicht W3Schools.

          Selbst W3Fools erkennt an, dass sich W3Schools gegenüber früher deutlich gebessert hat und „For many beginners, W3Schools has structured tutorials and playgrounds that offer a decent learning experience.“ Es ging überhaupt nicht darum, W3Schools schlechtzureden; demzufolge auch nicht darum, Alternativen dazu zu benennen.

          Blödsinnig ist hier von dem Lehrer an Ramazans Schule, W3C und W3Schools in einen Topf zu werfen. Das zeugt von enormer Unkenntnis und sollte einem Lehrer nicht passieren.

          LLAP 🖖

          --
          „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
          1. Hallo Gunnar,

            oh. Diesen Unfug hatte ich total übersehen. Ich wusste auch gar nicht, dass es eine w3fools Seite überhaupt gab und hatte deine Referenzen darauf immer als einen Seitenhieb auf w3schools gesehen.

            Rolf

            --
            sumpsi - posui - clusi
  5. Hallo Ramazan,

    habt ihr es schonmal mit den Browser-Entwicklerwerkzeugen versucht (zumeist mittels F12 Taste zu öffnen)?

    Rolf

    --
    sumpsi - posui - clusi