FrageAntwort – Referenz
Alles auf einen Blick. Wie die Teile zusammenspielen, zeigen die Beispiele in der Navigation.
Das EditorTemplate rendert eine Frage samt Antwortmöglichkeit und schickt sie einzeln und asynchron an den Server. Es bringt Formular, Absenden-Schaltfläche und Ajax-Ablauf selbst mit.
Einbindung
@for (var idx = 0; idx < Model.FrageAntwortListe.Count; idx++)
{
@Html.EditorFor(x => x.FrageAntwortListe[idx], UiEditor.Kompetenzen.FrageAnwort)
<hr />
}
Den Templatenamen liefert die Konstante UiEditor.Kompetenzen.FrageAnwort aus
FMH.Komponente.Kompetenzen. Ihr Wert schreibt sich ohne das zweite «t», wie die Datei
FrageAnwort.cshtml. Angegeben werden muss er, weil FrageAntwortViewModel keinen [UIHint] trägt.
Die Modellklassen
BeurteilungViewModel – die Klammer um die Fragen:
| Eigenschaft | Bedeutung |
|---|---|
FrageAntwortListe |
Die Fragen. Über sie läuft die Schleife in der View. |
FachDelegierterFmhId, FachDelegierterName |
Der Fachdelegierte. Vom Template nicht gerendert – für die eigene Seite. |
FachfremdDelegierterFmhId, FachfremdDelegierterName |
Dasselbe für den fachfremden Delegierten. |
FrageAntwortViewModel – eine Frage:
| Eigenschaft | Bedeutung |
|---|---|
Id |
Schlüssel der Frage. Geht als verstecktes Feld mit und ist die Zuordnung im Endpunkt. |
Reihenfolge |
Wird der Frage vorangestellt («1. …»). Sortiert wird nicht automatisch. |
Frage |
Der Fragetext. Geht ebenfalls als verstecktes Feld mit. |
AktuelleRolle |
Steuert die gesamte Darstellung, siehe unten. |
AntwortFachDelegierter |
Die Antwort des Fachdelegierten (AntwortTyp). |
AntwortTextFachDelegierter |
Die Begründung dazu, mehrzeilig. |
AntwortFachFremdDelegierter |
Die fachfremde Antwort. |
AntwortTextFachFremdDelegierter |
Die Begründung dazu. |
AntwortSelection |
Die angebotenen Antworten als SelectListItem. Vorbelegt mit «Ja» und «Nein». |
HatFachFremdDelegierterBeantwortet |
Ob eine fachfremde Antwort vorliegt – nur dann zeigt das Template sie dem Fachdelegierten. |
IstUneinig |
Ob beide Rollen geantwortet haben und die Antworten voneinander abweichen. |
GibAntwortTypText(typ) |
Der Anzeigetext zu einem AntwortTyp aus AntwortSelection. |
Die Aufzählungen
Rolle – wer die Frage gerade vor sich hat:
| Wert | Bearbeitet | Angezeigt | Speichern-Schaltfläche |
|---|---|---|---|
FachDelegierter |
AntwortFachDelegierter |
die fachfremde Antwort, sofern vorhanden | ja |
FachFremdDelegierter |
AntwortFachFremdDelegierter |
die Antwort des Fachdelegierten | ja |
Abgeschlossen |
– | beide Antworten | nein |
None |
– | beide Antworten | ja |
AntwortTyp – die Antwort selbst: Unbeantwortet (0), Ja (1), JaMitVorbehalt (2), Nein (3).
Angeboten werden über AntwortSelection zunächst nur Ja und Nein; JaMitVorbehalt und
Unbeantwortet erscheinen erst, wenn einer der beiden Werte bereits gesetzt ist. Alte Beurteilungen
bleiben so lesbar, ohne dass die Auswahl für neue Fälle wächst.
AntwortStatus – der Gesamtstand für die Rückmeldung: Unbeantwortet (0),
TeilweiseBeantwortet (1), KomplettBeantwortet (2).
Die Endpunkte
Das Template baut die Adresse seines Formulars ohne Controllernamen. Es postet damit an den Controller, der die Seite gerendert hat, dort müssen die Actions liegen:
| Rolle | Action |
|---|---|
FachDelegierter |
AntwortFD |
FachFremdDelegierter und alles Übrige |
AntwortFFD |
Beide nehmen ein flaches FrageAntwortViewModel entgegen:
[HttpPost]
public IActionResult AntwortFD(FrageAntwortViewModel modell)
Das ist kein Versehen: Das Skript der Komponente kürzt beim Absenden jeden Feldnamen auf sein
letztes Segment, aus FrageAntwortListe[0].Id wird Id. Ein Parameter, der die Liste erwartet,
bliebe deshalb leer.
Die Antwort des Endpunkts
AntwortResultat:
| Eigenschaft | Wirkung |
|---|---|
Nachricht |
Text der Snackbar, die die Komponente einblendet. |
Status |
AntwortStatus; reine Information für den Browser, die Komponente wertet ihn nicht aus. |
IconTyp |
Material-Design-Code des Snackbar-Symbols. Vorgabe check_circle; über IconTypeDictionary.Get(IconType.…) aus einem IconType zu gewinnen. |
Metadaten |
Frei belegbares Wörterbuch. Geht unverändert an das Browser-Ereignis. |
Für den Fehlerfall den Statuscode auf 400 setzen und ein AntwortResultat mit gefüllter
Nachricht zurückgeben, das Skript zeigt sie als Fehler-Snackbar und markiert die Schaltfläche.
Das Browser-Ereignis
Nach jeder erfolgreich gespeicherten Antwort löst die Komponente am window ein CustomEvent
namens FrageAntwortStatus aus. Sein detail ist das AntwortResultat als JSON-Objekt,
also Nachricht, Status, IconTyp und Metadaten in Pascal Case.
window.addEventListener('FrageAntwortStatus', function (ereignis) {
var resultat = ereignis.detail;
});
Das Ereignis wird nur ausgelöst, wenn die Antwort ein Objekt ist. Antwortet der Endpunkt mit einer blossen Zeichenkette, erscheint die Snackbar, aber kein Ereignis.
Was das Template selbst erledigt
- Ein Formular je Frage. Die Seite darf sie nicht in ein weiteres Formular einschliessen, verschachtelte Formulare erlaubt HTML nicht.
- Absenden per Ajax, inklusive Sperren und Freigeben der Schaltfläche: Sie startet gesperrt und wird erst durch eine Änderung an Auswahl oder Text wieder aktiv.
- Snackbar mit der Rückmeldung des Endpunkts.
Gestaltung
Die Klassen (frage-antwort--container, frage-antwort--antwort-fd-…) stecken im SCSS-Bundle
dieses Pakets, der Ajax-Ablauf in jquery-fmh-sitesetup.js der Basis. Fehlt die Einrichtung dafür,
bleibt ein ungestaltetes Formular, das die Seite neu lädt; was dazugehört, steht unter
Vorbedingungen.