Felder in Formularen ausblenden, wenn Checkbox nicht angewählt wurde

  • Hallo,


    der Wert der an deine *EditForm aus der Datenbank übergeben wird, ist wahrscheinlich 0. Das wundert mich nur, da du scheinbar deinstalliert hast, aber der Eintrag noch da ist. Dein Array beginnt bei 1 und hat kein Index 0.

    ->options([1 => 'wcf.acp.sar.ship.tier1', 2 => 'wcf.acp.sar.ship.tier2', 3 => 'wcf.acp.sar.ship.tier3'])

    Nutz doch einfach ein indiziertes Array ohne explizite Angabe der Schlüssel.

    Edited 7 times, last by itsmeJAY (April 21, 2024 at 9:48 PM).

  • Hallo,

    du kannst es doch so machen:

    PHP
    ->options(['wcf.acp.sar.ship.tier1', 'wcf.acp.sar.ship.tier2', 'wcf.acp.sar.ship.tier3'])

    Du solltest bei der verkürzten Array Syntax [] bleiben.

  • Das hatte ich probiert... damit ging es nicht....

    Jetzt habe ich aber folgendes, was auch funktioniert:


    Damit kann ich alle Edit-Icons anklicken ohne Fehler und auch die Namen in der Liste ohne Fehler. ABER:

    In der Auswahl in dem Select-Options ist nun logischerweise auch zwei-Mal die ' 0 '...

    Das mit dem roten Pfeil kommt anscheinend immer. Und ich möchte es ja nicht. Bzw. ich möchte das "wcf.acp.sar.tier0" nicht.

    Denn hier wird das Value " 0 " übergeben. Was ja angeblich fehlte. Aber das, so denke ich, wird doch auch bei der "(keine Auswahl)" übergeben...

    Und mit der ' 0 ' ist ja auch mein Ausfüllen nicht korrekt. Ich benötige ja eine Positive Zahl als Value. Also entweder die 1, 2 oder 3. Aber nicht die 0.

    Wieso macht er das? Ich kann sogar den ersten Eintrag "wcf.acp.sar.tier0" auswählen, ohne das er meckert, es wäre nichts ausgewählt. Aber hier ist das Value wie gesagt ' 0 ' und damit kann ich nichts anfangen.

    Eine Lösung A: wäre, den ersten Eintrag auszublenden... (keine Auswahl) und dann zusätzlich noch eine Validierung einzubauen, der dann bei Value = ' 0 ' einen Warnhinweis macht, dass man ein positives Value auswählen muss,

    oder B: man bekommt es hin, dass ich OHNE den Eintrag "wcf.acp.sar.tier0" das Select-Field erstellen und auswerten kann, ohne dass beim Editieren dann der Fehler kommt: "unknow Value '0'".

    Wie macht man das?

    oder Lösung C:

    ich muss die Datenbank umbauen. Das in der Datenbank als Default der Wert 3 gesetzt wird, der dann für mich bedeutet, 3 ich gleich KEIN Eintrag. Und setze dann mit dem Abfragen des Select-Fieldes folgende Werte :

    Value 0 = Tier 1

    Value 1 = Tier 2

    Value 2 = Tier 3

    Value 3 = keine Auswahl


    Das wäre dann nur so machbar...

  • Hallo,

    Damit kann ich alle Edit-Icons anklicken ohne Fehler und auch die Namen in der Liste ohne Fehler.

    Dann klappt das ja auch nun. :)

    Das mit dem roten Pfeil kommt anscheinend immer. Und ich möchte es ja nicht. Bzw. ich möchte das "wcf.acp.sar.tier0" nicht.

    oder B: man bekommt es hin, dass ich OHNE den Eintrag "wcf.acp.sar.tier0" das Select-Field erstellen und auswerten kann, ohne dass beim Editieren dann der Fehler kommt: "unknow Value '0'".

    Wie macht man das?

    Dann nimm wcf.acp.sar.tier0 doch aus dem Array, wenn Du es nicht brauchst. Dann wäre ja auch:

    Value 0 = Tier 1

    Aber das, so denke ich, wird doch auch bei der "(keine Auswahl)" übergeben...

    Nein, der Wert ist serverseitig nicht gesetzt wenn nichts gewählt wurde. Dein Problem wird hier liegen:

    maxTier TINYINT( 1 ) NOT NULL DEFAULT '0' ,

    Wenn im Query kein Wert explizit gesetzt wird, wird der default-Wert genommen. Und diesen hast Du mit 0 angegeben.

    Unabhängig davon, dass ich die Tabelle so nicht anlegen würde: Wie wäre es mit:

    maxTier TINYINT(1) DEFAULT NULL

    Dann sollte es auch klappen.


    Ganz einfach erklärt/zusammengefasst: Du hast in deinem Array vorher bei 1 gestartet und den Wert 0 gab es im Array schlicht nicht. Deine Datenbank setzt 0 aber derzeit als Standardwert, wenn es keinen gibt bzw. bei Anlage kein Wert gewählt wurde. Nun rufst Du deine EditForm auf, der FormBuilder versucht den Wert 0 zu finden (weil dieser in der Datenbank genau so drin steht), aber dieser existierte im Array nicht. Sieh demnach zu, dass deine Datenbank 0 nicht als Standardwert setzt und bearbeite dein Array einfach so, wie Du möchtest. Dann sollte alles klappen. Es hat also nichts damit zutun:

    Denn hier wird das Value " 0 " übergeben. Was ja angeblich fehlte. Aber das, so denke ich, wird doch auch bei der "(keine Auswahl)" übergeben...

    Und mit der ' 0 ' ist ja auch mein Ausfüllen nicht korrekt. Ich benötige ja eine Positive Zahl als Value. Also entweder die 1, 2 oder 3. Aber nicht die 0.

    Wieso macht er das? Ich kann sogar den ersten Eintrag "wcf.acp.sar.tier0" auswählen, ohne das er meckert, es wäre nichts ausgewählt. Aber hier ist das Value wie gesagt ' 0 ' und damit kann ich nichts anfangen.

    Edited 2 times, last by itsmeJAY (April 22, 2024 at 9:00 PM).

  • Ah... ok... jetzt macht die Fehlermeldung auch irgendwie Sinn...

    Nochmal vielen Dank für die ausführliche und vor allem verständliche Erklärung.

    Ich werde dann mal meine gesamte Datenbank entsprechend so umbauen (müssen). ;)

    Der Test erfolgt dann in Kürze... Ich schreibe dann mal hier die Ergebnisse.


    itsmeJAY Aber noch mal zum Verständnis: Wenn ich nun in der Datenbank-Struktur den "Default = '0'" einfach wegfallen lasse, dann wird das System auch nicht meckern, wenn ich ein Array dort als "Options" angebe, welches NICHT ein Value von '0' enthält? Oder muss immer ein Value von '0' in diesem Array vorhanden sein?


    Kannst du dir mal diese DB-Struktur anschauen bitte:

    Ist das so dann OK oder würdest du da noch Änderungen einbringen?

    Gruß
    Markus

    Mitglied aus dem Kartell...

    Das Kartell

    Edited once, last by MDMAN (April 23, 2024 at 6:02 AM).

  • Hallo,

    itsmeJAY Aber noch mal zum Verständnis: Wenn ich nun in der Datenbank-Struktur den "Default = '0'" einfach wegfallen lasse, dann wird das System auch nicht meckern, wenn ich ein Array dort als "Options" angebe, welches NICHT ein Value von '0' enthält? Oder muss immer ein Value von '0' in diesem Array vorhanden sein?

    wieso sollte das System dann meckern? Der Wert 0 ist dann doch gar nicht mehr existent. 0 wurde doch nur "gesucht", weil du deine Spalte in der Tabelle falsch angelegt hast. Ich glaube, Du hast noch nicht im Detail verstanden, warum das so ist. Es ist Dir (wahrscheinlich) folgendes passiert:

    1. Du hast dein Paket installiert. Die Spalte maxTier wurde mit NOT NULL (darf also nicht leer sein!) und dem default-Wert 0 angelegt. Siehe:
      maxTier TINYINT( 1 ) NOT NULL DEFAULT '0' ,
    2. Du hast deine *AddForm ausgefüllt um einen Eintrag in der Datenbank anzulegen, aber im SelectionFormField nichts ausgewählt. Demnach war das Feld null (leer/nicht gesetzt). Da der Wert in der Datenbank aber nicht null sein darf wurde der Datensatz mit dem Wert 0 angelegt. Bitte beachte hier, dass null und 0  nicht das gleiche ist. NULL repräsentiert einen fehlenden oder unbekannten Wert, der keinen Dateninhalt hat, während die Zahl 0 einen konkreten numerischen Wert darstellt. Würde das Feld "Haustiere" heißen und dort würde eine 0 stehen, hat der Benutzer explizit angegeben, dass er 0 Haustiere hat. Steht dort allerdings NULL, hat er gar keine Auswahl getätigt und kann in der Theorie unendlich viele Haustiere haben.
    3. Im Anschluss hast Du deine *EditForm aufgerufen um den zuvor angelegten Eintrag zu bearbeiten. Der FormBuilder hat nun versucht die Inhalte aus der Datenbank "aufzulösen", allerdings steht in der Spalte maxTier eine valide 0. Da deine options und dein Array aber so aussah:
      ->options([1 => 'wcf.acp.sar.ship.tier1', 2 => 'wcf.acp.sar.ship.tier2', 3 => 'wcf.acp.sar.ship.tier3'])
      wurde der Index 0 nicht gefunden, daher hast Du die Fehlermeldung bekommen:
      Unknown value '0' for field 'maxTier'.

    Du kannst das Array ruhig so lassen mit den Schlüsseln 1 bis 3. Wenn der Benutzer aber nichts ausfüllt, darf nicht 0 in die Spalte geschrieben werden, weil 0 in der Theorie ein Schlüssel des Arrays sein könnte und ein gültiger Wert ist, denn:

    PHP
    $array = [1 => 'wcf.acp.sar.ship.tier1', 2 => 'wcf.acp.sar.ship.tier2', 3 => 'wcf.acp.sar.ship.tier3'];
    echo $array[0] // würde zum Fehler führen, da der Schlüssel 0 nicht existent ist
    echo $array[1] // würde wcf.acp.sar.ship.tier1 ausgeben
    $array = [ 'wcf.acp.sar.ship.tier1', 'wcf.acp.sar.ship.tier2', 'wcf.acp.sar.ship.tier3'];
    echo $array[0] // würde wcf.acp.sar.ship.tier1 ausgeben
    echo $array[1] // würde wcf.acp.sar.ship.tier2 ausgeben

    Indizierte Arrays beginnen standardmäßig bei 0. Daher ist dein default-Wert "0" in der Datenbank (obwohl er hätte null sein müssen) mit den options "kollidiert".

    Ist das so dann OK oder würdest du da noch Änderungen einbringen?

    Das musst Du selber entscheiden, grundsätzlich würde ich aber default 0 immer überdenken. Zusätzlich würde ich die Tabelle, wie in der Dokumentation angegeben, über die API erstellen:

    Part 1 - WoltLab Suite Documentation

    Edited 5 times, last by itsmeJAY (April 23, 2024 at 10:21 AM).

  • itsmeJAY Oh... jetzt hat es schon wieder "klick" gemacht. Danke für die ausführliche Erklärung, die ja auch vollkommen logisch ist. Das war mir so nicht bewusst. Aber nun versuche ich mal das entsprechend umzusetzen.


    Und habe schon wieder was gelernt. Das man im WSC auch eine Funktion hat um Tabellen bzw. Datenbanken entsprechend zu Erweitern und Tabellen zu "create"n. Ich wäre nie auf die Idee gekommen, die DatabaseTable:create()-Funktion zu nutzen und direkt anzusprechen. Dachte das geschieht eigentlich immer über die install.sql - Datei. Der PiP würde ja dann auch genau diese Funktion nutzen, denke ich mal.

    Ich werde meine Tabellen-Struktur dann mal überdenken. Aber so wie es oben steht, sollte es dann keine Probleme mehr geben, denke ich mal...


    Vielen Dank noch mal für die ausgiebige Hilfestellung hier!

  • itsmeJAY

    Jetzt habe ich folgende Änderungen durchgeführt:

    in der Form sieht es nun so aus:

    Wenn ich nun die Seite aufrufe, kommt folgender Fehler:

    Das sieht also so aus, als ob er den Fehler schon wirft, bevor das Value gesetzt wurde. Das ist natürlich alles andere als schön.

    Jetzt noch mal die Frage:

    Wie kann ich das ausgewählte Value des 1. Select-Fields verwenden, um dann die Daten zu laden, die ich für das 2. Select-Field verwenden muss?

    Anscheinend wird der Parameter nicht gesetzt mit der Funktion:

    Code
    $previousField = $this->form->getNodeById('systemID'),

    gibt es da noch eine andere Möglichkeit?

    Es muss doch möglich sein, das Value entsprechend vor dem Laden der Values für das 2. Select-Feld zu erhalten. Damit ich damit dann den Inhalt des 2. Feldes entsprechend steuern kann...

    Ansonst gibt es hier nur noch die Alternative, alle Ergebnisse aus der Datenbank manuell zu laden und dann in einer Foreach-Schleife oder mit einer Array-Funkion nur nach den passenden Inhalten zu suchen und damit dann ein neues Array bauen, welches ich dann als "->options"- Array verwenden kann.


    Nur dann kommt gleich die nächste Frage, wie kann ich denn in dem ganzen Code für die Form-Felder meinen eigenen Code einbauen, ohne dass es zu Fehler kommt. Sobald ich eine "if - Schleife" einbauen möchte, kommt immer eine Fehlermeldung.

    Es ist alles sehr unschön...


    Gibt es denn irgendwelche Möglichkeiten?

  • Hallo,


    ich habe es zum Beispiel so gemacht. Müsstest Du für deine Bedürfnisse umschreiben. Hier siehst Du aber den Aufbau ganz gut.

  • itsmeJAY Ich habe es jetzt mal versucht mit deiner Lösung... Soweit bin ich gekommen:

    Laut IDE gibt es keine Fehler und auch das Ausführen im Browser wirft keine Fehler zurück.

    Allerdings habe ich nun das Problem, dass der große Container um diese Select-Fields nicht angezeigt wird. Es sollte ein Container noch vorhanden sein mit der Überschrift "location". Dieser wird NICHT angezeigt.

    Des Weiteren kommt auch das nächste Feld nicht. Sobald ich im Select-Field etwas auswähle, sollte doch das nächste Select-Field erscheinen mit der nächsten Abfrage. Das erscheint aber nicht.


    ALso diese Lösung funktioniert auch nicht wirklich...

  • itsmeJAY Also egal wie ich es versuche zu Erstellen, ich bekomme es nicht hin, dass ich das Value aus dem 1. Select-Feld dann für die Auswahl im 2. Select-Feld benutzen kann und dann das Value des 2. Select-Feldes für die Auswahl des 3. Select_Feldes benutzen kann.

    Ich habe da schon einige Sachen ausprobiert, aber es funktioniert einfach nicht.

    Hat da noch einer irgendeine Idee?

    Vielen Dank schon mal...

  • Das was du dort versuchst wird leider so nicht funktionieren. Die Code in der createForm() wird einmal ausgeführt wenn deine Seite geladen wird, und entsprechend hast du keinen Wert für das Form-Element systemID.

    Was du machen müsstest, wäre folgendes:
    Du erstellst für jede systemID ein eigenes Selection-Feld für planetID, welches nur angezeigt wird, wenn die jeweilige systemID ausgewählt wurde.
    Dann wird gleichzeitig immer maximal ein Selection-Feld pro planetID angezeigt. Du musst natürlich dann noch einen Data-Handler der Form hinzufügen, damit an did. Action-Class die korrekten Werte übermittelt werden.
    Beachte auch, du kannst nicht die selbe ID/Name für das Feld hier verwenden, nutze daher so etwas wie planetID${systemID}.

    Das gleiche machst du dann für moonID :)

  • Uff.... das wird aber eine riesen-Arbeit... Es sollen ja irgendwann bis zu 100 System, in jedem System bis zu 100 Planeten und eventuell an jedem Planeten bis zu 10 Monde vorhanden sein...

    Also so wie in Elite Dangerous oder Eve Online...


    Das wird ja ein RIESEN-Datenpaket werden...

    Habe mir aber sowas schon gedacht, dass es so einfach nicht möglich wird...

    Könnte man denn nicht per Javascript die Daten laden, die benötigt werden?

    Cyperghost

  • Cyperghost Hört sich gut an...

    Jetzt mal für Anfänger:

    Wie genau muss ich das Anstellen? Wo kann ich da mich einklinken und alles in JS übertragen? Wie muss ich denn meine Form entsprechend anpassen?

    Hier mal die Form, wie ich Sie jetzt habe...

    Die ersten drei Select-Form sind entsprechend so umzubauen, dass es halt immer auf die Auswahl des vorherigen SelectForms ankommt...


    Wie kann ich denn hier entsprechend JS einbauen?


    Und das entsprechende Template dazu:

    Code
    {include file='header'}
    
    {event name='beforeForm'}
    
    {@$form->getHtml()}
    
    {event name='afterForm'}
    
    {include file='footer'}
  • Du kannst dies über zwei Wege machen. Entweder du erstellst dir verschiede Action-Klassen oder aber auch die packst alles in deine DatabaseObjectAction in verschiedenen Funktionen.

    Als Beispiel kannst du folgendes hier nehmen

    1. https://github.com/WoltLab/WCF/bl…ction.class.php
    2. https://github.com/WoltLab/WCF/bl…ction.class.php

    Über TypeScript kannst du dann mit den Rückgabewert der Form bzw. der Auswahl eine neue Form bei successCallback erstellen

    Und in deiner DatabaseObjectAction müsstest du entsprechend wie folgt etwas haben


    p.s.

    Ich habe diesen Code nicht getestet, diese sollte aber theoretisch funktionieren :D

  • Uff... vielen Dank Cyperghost . Ich habe den Javascript Code zwar so noch nicht ganz gecheckt, aber ansätze davon habe ich so halbwegs verstanden.

    Ich muss dann nur in Zeile 44 zum Beispiel

    Code
    $this->parameters['data'] ?? []);

    In der letzen eckigen Klammer dann die fieldID des Feldes zum Auslesen eintragen?

    Über TypeScript

    TypeScript muss ich doch beim Installieren des Paketes über den Ordner /ts/Name.ts compilen und dann automatisch installieren lassen, oder?

    protected ?DialogFormDocument $form = null;

    Ist das ein Versehen, dass in Zeile 1 in dieser Zeile ein " ? " steht oder muss das so?

    $id = 'planetSelection';

    In Zeile 20 hast du "planetSelection" geschrieben. Die ID hier muss doch irgendein Datenbank-Feld sein oder nicht? Dann kann es doch nur die PlanetID sein. Oder irre ich mich da?

    Hier mal die Datenbank-Struktur (Ausschnitt):

    So ganz verstehe ich die Funktion da oben nicht...

    Ich trage in der Datenbank in der sar_planet in der Spalte "parentSystemID" die ID des Systems ein.

    Wenn ich nun in dem 1. Select-Field ein System auswähle, habe ich ja logischerweise dessen systemID.

    Diese suche ich dann in der sar_planet-Tabelle in der Spalte parentSystemID. Also ist die sar_planet.parentSystemID = sar_system.systemID

  • Ist das ein Versehen, dass in Zeile 1 in dieser Zeile ein " ? " steht oder muss das so?

    Google ist dein Freund.

    Ich empfehle dir jemanden zu engagieren, der dich kostenpflichtig unterstützt. Erstens ist deine eigene Zeit doch zu kostbar, als dass du hier ein Vielfaches investieren musst, um aufs Ergebniss zu kommen. Zweitens ist es den anderen hier unfair gegenüber, dass du selbst so wenig Eigeninitiative zeigst und hier "Kunden helfen Kunden" eher zu "Kunden arbeiten für Kunden" machst.

    Sonst: Lies dir selbst Code des WSC durch und versuche ihn mit Google zu verstehen. So kommt man um einiges weiter. Auch fremde Plugins kann man so analysieren.

    Viele Grüße, Julian

    PS: Eine ausführlichere Antwort gibt's kostenlos von mir leider nicht 😅

    Managed Webhosting, hochwertige Plugins und individuelle Auftragsarbeiten:

    Julian-Pfeil.de

  • In der letzen eckigen Klammer dann die fieldID des Feldes zum Auslesen eintragen?

    Das brauchst du nicht verändern, alle Inputs liegen in data vor.

    In Zeile 20 hast du "planetSelection" geschrieben. Die ID hier muss doch irgendein Datenbank-Feld sein oder nicht? Dann kann es doch nur die PlanetID sein. Oder irre ich mich da?

    Nein, dies bezieht sich nicht auf interne Strukturen deiner Datenbank oder Spalten etc. dies ist nur eine eindeutige ID für das Formular und hat ansonsten keine wirklich Bedeutung. Diese ID darf aber zeitgleich nicht doppelte verwendet werden. Und solltest du auch bei anderen Formularen anpassen um entsprechend zu wissen um welches es sich handelt.

    Ist das ein Versehen, dass in Zeile 1 in dieser Zeile ein " ? " steht oder muss das so?

    PHP: Type declarations - Manual

    TypeScript muss ich doch beim Installieren des Paketes über den Ordner /ts/Name.ts compilen und dann automatisch installieren lassen, oder?

    TypeScript - WoltLab Suite Documentation

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!