Likertskala
Mehrere Skalen gruppieren
LikertSkalaGroup rendert mehrere Skalen als einen Block. Konfiguriert wird nicht mehr im Markup, sondern am LikertSkalaGroupModel – dafür ist der Aufruf in der View immer derselbe.
@model KompetenzGruppeViewModel
@* Bei einer Gruppe steht die Rolle am LikertSkalaGroupModel und gilt für alle Skalen gemeinsam. *@
<div class="alert alert-secondary py-2 px-3 mb-3">
<strong>Rolle: @Model.RolleName</strong><br />
<span class="small">@Model.RolleHinweis Sie gilt für alle Skalen der Gruppe gemeinsam.</span>
</div>
@* Mehrere Skalen als ein Block: LikertSkalaGroup rendert für jeden Eintrag in LikertSkalaGroup eine
eigene Skala. Konfiguriert wird hier nichts mehr im Markup – Spalten, Texte, Bearbeitungsmodus und
Erfüllungsgrad stehen am LikertSkalaGroupModel, also dort, wo auch die Daten herkommen.
Der Builder ist nicht generisch: Die Gruppe arbeitet fest mit int-Skalenwerten. *@
<form method="post" asp-area="Kompetenzen" asp-controller="LikertSkalaBeispiel" asp-action="Gruppe">
@Html.HiddenFor(m => m.Id)
@Html.Fmh(Fmh.LikertSkalaGroup()
.Id("lk-gruppe")
.Bind(Model.Tabellen, Html.NameFor(m => m.Tabellen).ToString()))
@Html.Fmh(Fmh.Button()
.Text("Speichern")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-3" }))
</form>
<div class="mt-3">
@Html.Fmh(Fmh.Button()
.Text("Ausgangslage wiederherstellen")
.Size(ButtonSize.Sm)
.Outline()
.Action("Zuruecksetzen", "LikertSkalaBeispiel", new { area = "Kompetenzen", beispiel = "gruppe" }))
</div>
using FMH.Komponente.Kompetenzen.Ui.Controls.LikertSkala;
namespace FMH.Komponente.WebUI.Areas.Kompetenzen.Models
{
/// <summary>
/// Das ViewModel mehrerer Likertskalas, die als ein Block erfasst werden.
/// </summary>
/// <remarks>
/// Die Gruppe bringt ihr Modell selbst mit: <see cref="LikertSkalaGroupModel" /> hält die
/// einzelnen Skalen samt deren Spalten und Texten. Das ViewModel der Seite trägt es nur.
/// </remarks>
public class KompetenzGruppeViewModel
{
/// <summary>
/// Holt oder setzt die fachliche Id, an der der POST hängt.
/// </summary>
public int Id { get; set; }
/// <summary>
/// Holt oder setzt die Gruppe der Skalen. Der Name dieser Eigenschaft ist der zweite
/// Parameter von <c>Bind(...)</c>; die Feldnamen der Radiobuttons lauten daraus
/// <c>Tabellen.LikertSkalaGroup[0].Likertskala[0].SelfAssessmentValue</c>.
/// </summary>
public LikertSkalaGroupModel Tabellen { get; set; } = new LikertSkalaGroupModel();
/// <summary>
/// Holt den Hinweistext zur Rolle. Sie steht bei einer Gruppe am
/// <see cref="LikertSkalaGroupModel.AssessmentType" /> und gilt für alle Skalen gemeinsam.
/// </summary>
public string RolleHinweis => Rollen.Hinweis(this.Tabellen.AssessmentType);
/// <summary>
/// Holt den Kurznamen der Rolle.
/// </summary>
public string RolleName => Rollen.Kurzname(this.Tabellen.AssessmentType);
}
}
using System.Collections.Generic;
using FMH.Komponente.Kompetenzen.Ui.Controls.LikertSkala;
using FMH.Komponente.Kompetenzen.Ui.Controls.LikertSkala.Daten;
namespace FMH.Komponente.WebUI.Areas.Kompetenzen.Models
{
/// <summary>
/// Die Testdaten der Demo. Ohne Datenbank, dafür fachlich nahe an einem Zeugnis: Lernziele mit
/// Code, Text und den bereits erfassten Einschätzungen.
/// </summary>
/// <remarks>
/// Jede Methode liefert bewusst eine **neue** Liste. Die Zeilen sind veränderlich, und der POST
/// eines Beispiels bindet direkt auf sie – eine prozessweit geteilte Liste würde sich zwischen
/// den Seiten gegenseitig überschreiben.
/// </remarks>
public static class LernzielDaten
{
/// <summary>
/// Die Skalenwerte als Spaltendefinition, wie sie aus einer Konfigurationstabelle käme.
/// </summary>
/// <remarks>
/// **Die Reihenfolge ist fachlich bedeutsam**: Der Erfüllungsgrad vergleicht die Position
/// der Spalten, nicht deren Werte. Die beste Stufe steht deshalb zuvorderst, «nicht
/// beurteilbar» als Nicht-Stufe zuhinterst.
/// </remarks>
/// <returns>Die Spalten der Skala.</returns>
public static IList<LikertSkalaHeaderColumn<int>> Stufen()
{
return new List<LikertSkalaHeaderColumn<int>>
{
new LikertSkalaHeaderColumn<int> { Value = 4, Text = "Stufe 4", Width = 130 },
new LikertSkalaHeaderColumn<int> { Value = 3, Text = "Stufe 3", Width = 130 },
new LikertSkalaHeaderColumn<int> { Value = 2, Text = "Stufe 2", Width = 130 },
new LikertSkalaHeaderColumn<int> { Value = 1, Text = "Stufe 1", Width = 130 },
new LikertSkalaHeaderColumn<int> { Value = 99, Text = "nicht beurteilbar", Width = 150 },
};
}
/// <summary>
/// Lernziele mit einer angefangenen Selbsteinschätzung – die Ausgangslage des Grundfalls.
/// </summary>
/// <returns>Die Zeilen der Skala.</returns>
public static IList<LikertSkalaRow<int>> Lernziele()
{
return new List<LikertSkalaRow<int>>
{
new LikertSkalaRow<int> { Code = 5, Text = "Patientinnen und Patienten umfassend beraten und begleiten", SelfAssessmentValue = 1 },
new LikertSkalaRow<int> { Code = 7, Text = "Befunde strukturiert dokumentieren", SelfAssessmentValue = 2 },
new LikertSkalaRow<int> { Code = 9, Text = "Im interprofessionellen Team zusammenarbeiten" },
new LikertSkalaRow<int> { Code = 11, Text = "Eigene Grenzen erkennen und Hilfe anfordern", SelfAssessmentValue = 1 },
new LikertSkalaRow<int> { Code = 13, Text = "Regelmässig an Weiterbildungen teilnehmen" },
};
}
/// <summary>
/// Lernziele mit Überschrift je Zeile – Grundlage des Beispiels «Texte um die Skala».
/// </summary>
/// <returns>Die Zeilen der Skala.</returns>
public static IList<LikertSkalaRow<int>> LernzieleMitUeberschrift()
{
return new List<LikertSkalaRow<int>>
{
new LikertSkalaRow<int>
{
Code = 5,
Header = "Betreuung",
Text = "Kann Patientinnen und Patienten umfassend beraten, begleiten und betreuen und dabei deren Autonomie gebührend respektieren",
SelfAssessmentValue = 2,
},
new LikertSkalaRow<int>
{
Code = 7,
Header = "Kommunikation",
Text = "Kann komplexe Sachverhalte gegenüber Angehörigen verständlich darstellen",
},
new LikertSkalaRow<int>
{
Code = 9,
Header = "Zusammenarbeit",
Text = "Kann die eigene Rolle im interprofessionellen Team einnehmen und Aufgaben delegieren",
SelfAssessmentValue = 1,
},
};
}
/// <summary>
/// Kompetenzen mit Selbst- und Fremdeinschätzung – Grundlage der Beispiele
/// «Selbst- und Fremdeinschätzung» und «Erfüllungsgrad».
/// </summary>
/// <remarks>
/// <c>DegreeOfAchievementValue</c> ist die **geforderte** Stufe. Bewusst gemischt: erfüllt,
/// übererfüllt, nicht erreicht, ohne Anforderung und «nicht beurteilbar» – nur so lässt sich
/// die Prozentzahl im Kopf der Skala nachrechnen.
/// </remarks>
/// <returns>Die Zeilen der Skala.</returns>
public static IList<LikertSkalaRow<int>> Kompetenzen()
{
return new List<LikertSkalaRow<int>>
{
new LikertSkalaRow<int>
{
Code = 5,
Text = "Akutes Lungenödem «A»",
SelfAssessmentValue = 4,
ExternalAssessmentValue = 4,
DegreeOfAchievementValue = 4,
},
new LikertSkalaRow<int>
{
Code = 7,
Text = "Lungenembolie «A»",
SelfAssessmentValue = 3,
ExternalAssessmentValue = 4,
DegreeOfAchievementValue = 3,
},
new LikertSkalaRow<int>
{
Code = 9,
Text = "Akuter Myokardinfarkt ACS «A»",
SelfAssessmentValue = 3,
ExternalAssessmentValue = 2,
DegreeOfAchievementValue = 3,
},
new LikertSkalaRow<int>
{
Code = 11,
Text = "Hypertensive Krise «A»",
SelfAssessmentValue = 3,
ExternalAssessmentValue = 1,
},
new LikertSkalaRow<int>
{
Code = 13,
Text = "Arrhythmien und Rhythmusstörungen «A»",
SelfAssessmentValue = 3,
ExternalAssessmentValue = 99,
DegreeOfAchievementValue = 2,
},
new LikertSkalaRow<int>
{
Code = 15,
Text = "Aortendissektion (Erwachsene) «B»",
SelfAssessmentValue = 2,
ExternalAssessmentValue = 2,
DegreeOfAchievementValue = 2,
},
};
}
/// <summary>
/// Zwei Skalen mit unterschiedlichen Spalten als eine Gruppe – Grundlage des Beispiels
/// «Mehrere Skalen gruppieren».
/// </summary>
/// <returns>Das Modell der Gruppe.</returns>
public static LikertSkalaGroupModel Gruppe()
{
var gruppe = new LikertSkalaGroupModel
{
// Der Bearbeitungsmodus steht an der Gruppe, nicht an der einzelnen
// Skala: Wer eine Gruppe ausfüllt, tut das durchgehend in einer Rolle.
AssessmentType = Editable.ExternalAssessment,
GroupHeader = "Zwischenevaluation 2026",
Header = "Kompetenzen und Verhalten",
Introduction = "Bitte beide Tabellen vollständig ausfüllen.",
Footer = "Die Einschätzung wird mit der Kandidatin oder dem Kandidaten besprochen.",
};
var fachlich = new LikertSkalaModel
{
Id = 10,
LikerstSkalaHeader = "<h5>Fachliche Kompetenzen</h5>",
Header = "Kompetenz",
Introduction = "Vier Stufen, dazu «nicht beurteilbar».",
ShowDegreeOfAchievement = true,
Columns = Stufen(),
Likertskala = Kompetenzen(),
};
var verhalten = new LikertSkalaModel
{
Id = 12,
LikerstSkalaHeader = "<h5>Verhalten im Team</h5>",
Header = "Merkmal",
Footer = "Erfüllt bedeutet: im Alltag durchgehend beobachtbar.",
// Kein Skalenwert 0: Eine noch nicht beurteilte Zeile hat als int
// ebenfalls 0 und sähe sonst aus wie eine bewusste Antwort.
Columns = new List<LikertSkalaHeaderColumn<int>>
{
new LikertSkalaHeaderColumn<int> { Value = 1, Text = "Erfüllt", Width = 150 },
new LikertSkalaHeaderColumn<int> { Value = 2, Text = "Nicht erfüllt", Width = 150 },
},
Likertskala = new List<LikertSkalaRow<int>>
{
new LikertSkalaRow<int> { Code = 21, Text = "Pünktlichkeit", ExternalAssessmentValue = 1 },
new LikertSkalaRow<int> { Code = 23, Text = "Übergaben vollständig", ExternalAssessmentValue = 2 },
new LikertSkalaRow<int> { Code = 25, Text = "Rückfragen rechtzeitig gestellt" },
},
};
gruppe.LikertSkalaGroup.Add(fachlich);
gruppe.LikertSkalaGroup.Add(verhalten);
return gruppe;
}
}
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using FMH.Komponente.Kompetenzen.Ui.Controls.LikertSkala;
using FMH.Komponente.Kompetenzen.Ui.Controls.LikertSkala.Daten;
namespace FMH.Komponente.WebUI.Areas.Kompetenzen.Models
{
/// <summary>
/// Der Stand der Beispiele. Ohne ihn zeigte die Seite nach dem Absenden wieder die
/// Ausgangsdaten – die Wirkung einer Änderung wäre nicht zu sehen.
/// </summary>
/// <remarks>
/// Statt einer Datenbank eine prozessweite Ablage je Beispiel; nach einem Neustart der
/// Anwendung steht wieder die Ausgangslage. In einem Projekt steht an dieser Stelle das
/// Repository – der Ablauf ist derselbe.
/// <para>
/// <b>Übernommen wird über den <c>Code</c>, nicht die Position.</b> Aus dem Formular kommen nur
/// Code und die Einschätzung der aktuellen Rolle zurück; die geforderte Stufe, die Überschriften
/// und die Spalten stammen weiterhin aus der eigenen Quelle. Genau so gehört es auch in einem
/// Projekt gemacht: Der POST liefert Antworten, nicht die Konfiguration.
/// </para>
/// </remarks>
public static class LernzielZustand
{
private static readonly ConcurrentDictionary<string, LikertSkalaGroupModel> Gruppen =
new ConcurrentDictionary<string, LikertSkalaGroupModel>();
private static readonly ConcurrentDictionary<string, IList<LikertSkalaRow<int>>> Skalen =
new ConcurrentDictionary<string, IList<LikertSkalaRow<int>>>();
/// <summary>
/// Der aktuelle Stand einer einzelnen Skala; beim ersten Aufruf die Ausgangslage.
/// </summary>
/// <param name="beispiel">Der Schlüssel des Beispiels.</param>
/// <param name="ausgangslage">Liefert die Ausgangsdaten, wenn noch nichts erfasst wurde.</param>
/// <returns>Die Zeilen der Skala.</returns>
public static IList<LikertSkalaRow<int>> Skala(string beispiel, Func<IList<LikertSkalaRow<int>>> ausgangslage)
{
return Skalen.GetOrAdd(beispiel, _ => ausgangslage());
}
/// <summary>
/// Der aktuelle Stand einer Gruppe; beim ersten Aufruf die Ausgangslage.
/// </summary>
/// <param name="beispiel">Der Schlüssel des Beispiels.</param>
/// <param name="ausgangslage">Liefert die Ausgangsdaten, wenn noch nichts erfasst wurde.</param>
/// <returns>Das Modell der Gruppe.</returns>
public static LikertSkalaGroupModel Gruppe(string beispiel, Func<LikertSkalaGroupModel> ausgangslage)
{
return Gruppen.GetOrAdd(beispiel, _ => ausgangslage());
}
/// <summary>
/// Übernimmt die Antworten eines POST in den Stand einer einzelnen Skala.
/// </summary>
/// <param name="beispiel">Der Schlüssel des Beispiels.</param>
/// <param name="gepostet">Die Zeilen aus dem Formular.</param>
/// <param name="rolle">Die Rolle, in der erfasst wurde.</param>
/// <returns>Die Anzahl geänderter Zeilen.</returns>
public static int Uebernehmen(string beispiel, IList<LikertSkalaRow<int>> gepostet, Editable rolle)
{
if (Skalen.TryGetValue(beispiel, out var bestand) == false)
{
return 0;
}
return Uebernehmen(bestand, gepostet, rolle);
}
/// <summary>
/// Übernimmt die Antworten eines POST in den Stand einer Gruppe.
/// </summary>
/// <param name="beispiel">Der Schlüssel des Beispiels.</param>
/// <param name="gepostet">Die Gruppe aus dem Formular.</param>
/// <returns>Die Anzahl geänderter Zeilen über alle Skalen.</returns>
public static int UebernehmenGruppe(string beispiel, LikertSkalaGroupModel gepostet)
{
if (Gruppen.TryGetValue(beispiel, out var bestand))
{
// Die Rolle steht am Bestand: AssessmentType ist Konfiguration und wird nicht
// gepostet – am geposteten Modell stünde der Standardwert.
var anzahl = 0;
for (var idx = 0; idx < bestand.LikertSkalaGroup.Count; idx++)
{
var geposteteSkala = gepostet?.LikertSkalaGroup.ElementAtOrDefault(idx);
anzahl += Uebernehmen(
bestand.LikertSkalaGroup[idx].Likertskala,
geposteteSkala?.Likertskala,
bestand.AssessmentType);
}
return anzahl;
}
return 0;
}
/// <summary>
/// Verwirft den erfassten Stand eines Beispiels; der nächste Aufruf zeigt wieder die
/// Ausgangslage.
/// </summary>
/// <param name="beispiel">Der Schlüssel des Beispiels.</param>
public static void Zuruecksetzen(string beispiel)
{
Skalen.TryRemove(beispiel, out _);
Gruppen.TryRemove(beispiel, out _);
}
private static int Uebernehmen(IList<LikertSkalaRow<int>> bestand, IList<LikertSkalaRow<int>> gepostet, Editable rolle)
{
// In dieser Rolle sind die Radiobuttons gesperrt und senden nichts – ein POST darf den
// Stand deshalb nicht anfassen.
if (rolle == Editable.ExternalAssessmentReadOnly || gepostet == null)
{
return 0;
}
var anzahl = 0;
foreach (var zeile in gepostet)
{
var ziel = bestand.FirstOrDefault(vorhanden => vorhanden.Code == zeile.Code);
if (ziel == null)
{
continue;
}
if (rolle == Editable.ExternalAssessment)
{
if (ziel.ExternalAssessmentValue != zeile.ExternalAssessmentValue)
{
ziel.ExternalAssessmentValue = zeile.ExternalAssessmentValue;
anzahl++;
}
}
else if (ziel.SelfAssessmentValue != zeile.SelfAssessmentValue)
{
ziel.SelfAssessmentValue = zeile.SelfAssessmentValue;
anzahl++;
}
}
return anzahl;
}
}
}
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.Kompetenzen.Ui.Controls.LikertSkala.Daten;
using FMH.Komponente.WebUI.Areas.Kompetenzen.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Kompetenzen.Controllers.Beispiele
{
/// <summary>
/// Die Gegenstelle der Beispiele. Die Skala ist ein Eingabe-Steuerelement – ohne einen POST, der
/// die Antworten übernimmt, bliebe die halbe Erklärung offen.
/// </summary>
/// <remarks>
/// Alle Actions arbeiten nach dem PRG-Muster: übernehmen, Meldung merken, zurück auf die
/// Demo-Seite. Der Stand liegt in LernzielZustand, damit die Seite nach dem Absenden das
/// Erfasste zeigt und nicht wieder die Ausgangsdaten.
/// <para>
/// Übernommen wird über den Code der Zeile und nur der Wert der aktuellen Rolle. Alles andere –
/// die geforderte Stufe, die Spalten, die Texte – steht in keinem Formularfeld und kommt
/// weiterhin aus der eigenen Quelle.
/// </para>
/// </remarks>
[Area("Kompetenzen")]
public class LikertSkalaBeispielController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Einschaetzung(LernzielViewModel modell)
{
// Die Rolle kommt als Hidden-Feld mit und entscheidet, welcher der beiden Werte
// geschrieben wird. Der jeweils andere reist unverändert in seinem Hidden-Feld mit.
this.MeldeUebernahme(LernzielZustand.Uebernehmen("einschaetzung", modell.Likertskala, modell.Rolle), modell.Rolle);
return this.RedirectToAction("Einschaetzung", "Demo", new { area = "Kompetenzen", rolle = modell.Rolle });
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Erfuellungsgrad(LernzielViewModel modell)
{
this.MeldeUebernahme(LernzielZustand.Uebernehmen("erfuellungsgrad", modell.Likertskala, modell.Rolle), modell.Rolle);
return this.Zurueck(nameof(this.Erfuellungsgrad));
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Grundfall(LernzielViewModel modell)
{
this.MeldeUebernahme(LernzielZustand.Uebernehmen("grundfall", modell.Likertskala, modell.Rolle), modell.Rolle);
return this.Zurueck(nameof(this.Grundfall));
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Gruppe(KompetenzGruppeViewModel modell)
{
// Die Rolle steht bei einer Gruppe am Modell und wird nicht gepostet – der Zustand
// nimmt sie deshalb aus dem eigenen Bestand.
var anzahl = LernzielZustand.UebernehmenGruppe("gruppe", modell.Tabellen);
this.AddAlert(
anzahl == 0
? "Keine Änderung – es wurde nichts anders bewertet als zuvor."
: $"{anzahl} Bewertung(en) über alle Skalen übernommen.",
anzahl == 0 ? AlertType.Info : AlertType.Success,
autoHide: true);
return this.Zurueck(nameof(this.Gruppe));
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Texte(LernzielViewModel modell)
{
this.MeldeUebernahme(LernzielZustand.Uebernehmen("texte", modell.Likertskala, modell.Rolle), modell.Rolle);
return this.Zurueck(nameof(this.Texte));
}
/// <summary>
/// Verwirft den erfassten Stand eines Beispiels und zeigt wieder die Ausgangsdaten.
/// </summary>
/// <param name="beispiel">Der Schlüssel des Beispiels, zugleich der Name der Demo-Action.</param>
/// <param name="rolle">Die Rolle, in die zurückgekehrt wird (nur beim Beispiel «einschaetzung»).</param>
/// <returns>Die Umleitung auf die Demo-Seite.</returns>
public IActionResult Zuruecksetzen(string beispiel, Editable rolle = Editable.SelfAssessment)
{
LernzielZustand.Zuruecksetzen(beispiel);
this.AddAlert("Ausgangslage wiederhergestellt.", AlertType.Info, autoHide: true);
return this.RedirectToAction(DemoAction(beispiel), "Demo", new { area = "Kompetenzen", rolle });
}
/// <summary>
/// Der Schlüssel des Beispiels ist der kleingeschriebene Name der Demo-Action.
/// </summary>
/// <param name="beispiel">Der Schluessel des Beispiels.</param>
/// <returns>Der Name der Demo-Action.</returns>
private static string DemoAction(string beispiel)
{
switch (beispiel)
{
case "einschaetzung":
return "Einschaetzung";
case "erfuellungsgrad":
return "Erfuellungsgrad";
case "gruppe":
return "Gruppe";
case "texte":
return "Texte";
default:
return "Grundfall";
}
}
private void MeldeUebernahme(int anzahl, Editable rolle)
{
if (Rollen.IstBearbeitbar(rolle) == false)
{
// Gesperrte Radiobuttons senden nichts – ein POST aus dieser Rolle darf den Stand
// nicht anfassen.
this.AddAlert("Nur-Ansicht-Rolle – es wurde nichts übernommen.", AlertType.Warning, autoHide: true);
return;
}
this.AddAlert(
anzahl == 0
? $"Keine Änderung an «{Rollen.Kurzname(rolle)}» – es wurde nichts anders bewertet als zuvor."
: $"{anzahl} Bewertung(en) für «{Rollen.Kurzname(rolle)}» übernommen.",
anzahl == 0 ? AlertType.Info : AlertType.Success,
autoHide: true);
}
private IActionResult Zurueck(string action)
{
return this.RedirectToAction(action, "Demo", new { area = "Kompetenzen" });
}
}
}
Darstellung
Erfasst wird «definitive assessment»; «Self-assessment» steht als Markierung daneben. Sie gilt für alle Skalen der Gruppe gemeinsam.
Ein Zeugnis besteht selten aus einer Skala. Fmh.LikertSkalaGroup() rendert mehrere untereinander,
mit gemeinsamer Überschrift und gemeinsamem Bearbeitungsmodus:
@Html.Fmh(Fmh.LikertSkalaGroup()
.Id("lk-gruppe")
.Bind(Model.Tabellen, Html.NameFor(m => m.Tabellen).ToString()))
In der View steht damit nichts mehr über Spalten oder Texte. Alles davon liegt am
LikertSkalaGroupModel, also dort, wo auch die Daten herkommen – der übliche Fall, wenn Stufen und
Beschriftungen je Fachgebiet aus der Datenbank stammen.
| Am Gruppenmodell | Wirkung |
|---|---|
GroupHeader, Header, Introduction |
Blöcke über allen Skalen |
Footer |
Block unter allen Skalen |
AssessmentType |
gilt für alle Skalen; je Skala einstellbar ist er nicht |
LikertSkalaGroup |
die Skalen selbst, je als LikertSkalaModel |
Die einzelne Skala trägt ihre eigenen Spalten und Texte – im Beispiel eine fünfstufige Skala mit
Erfüllungsgrad und darunter eine zweistufige ohne. Bei den Texten aufpassen:
LikerstSkalaHeader ist der Titel über der Skala, Header die Überschrift der ersten
Spalte.
Was zu beachten ist
- Die Element-Ids vergibt der Gruppen-Builder aus seinem Präfix (
lk-gruppe-0,lk-gruppe-1). Wer eine Skala fachlich identifizieren muss, führt ihre Id in einem eigenen Hidden-Feld mit. - Die Konfiguration überlebt den POST nicht. Zurück kommen nur Zeilen mit Code, Text und
Einschätzung – Spalten, Überschriften, Einleitung, Fusstext und
AssessmentTypesind weg und müssen vor der nächsten Ausgabe neu gesetzt werden. Bei einer Gruppe fällt das stärker ins Gewicht als bei einer einzelnen Skala. - Auch
AssessmentTypekommt nicht zurück. Beim Übernehmen der Antworten ist deshalb die Rolle aus dem eigenen Bestand massgebend, nicht die des geposteten Modells – dort steht der Standardwert. - Die Feldnamen werden entsprechend tief:
Tabellen.LikertSkalaGroup[0].Likertskala[0].Code. Das Model-Binding kommt damit zurecht, solange die Eigenschaftsnamen ausNameForstammen.