Thomas Bandt

Über mich | Kontakt | Archiv

Back to the roots: Repeater und RadioButtons ohne JavaScript

Zur Problematik mit RadioButtons und Repeater-Control habe ich neulich schon etwas geschrieben, damals entschied ich mich etwas voreilig für den JavaScript-Workaround.

Nun hinterfrage ich Anwendungen fürs Web aber spätestens dann, wenn sie fertig sind, ob sie nicht auch ohne JavaScript laufen sollten. Denn es ist ziemlich sinnlos für wenige Teilfunktionen zwingend JavaScript vorauszusetzen, wenn der Großteil der Website/Anwendung auch ohne läuft.

So war es dann auch in dem Fall, also habe ich nach einer JavaScript-freien Lösung für das RadioButton-/Repeater-Problem gesucht. Letztendlich gibt es im Prinzip zwei Wege:

  1. Man manipuliert die Client-IDs der RadioButtons.
  2. Man lässt alles wie es ist, fragt das Ergebnis aber auf "die gute alte Weise" ab.

Ich halte 2. für die sinnvollere Lösung:

<asp:Repeater ID="ListPaymentMethods" runat="server">
    <ItemTemplate>
         <input type="radio" name="paymentMethod" id="paymentMethod_<%# Eval("ID") %>" value="<%# Eval("ID") %>" />
    </ItemTemplate>
</asp:Repeater>

Innerhalb des Repeaters wird also einfach ein klassisches, nicht serverseitiges, HTML-Control benutzt. Dadurch erzielt man die Eindeutigkeit des Namens, auf die es im Browser ankommt, damit der Benutzer keine Mehrfachauswahl tätigen kann.

Serverseitig wird das Ergebnis "wie früher" abgefragt:

private int GetPaymentMethodID()
{
    int paymentMethodID;
    int.TryParse(Request.Form["paymentMethod"], out paymentMethodID);
    return paymentMethodID;
}

Denn da ein PostBack nichts anderes ist als ein Senden von Formularinhalten via POST, erhält man mit jedem Button-Klick auch den gewählten Wert. Natürlich muss dieser nicht gesetzt sein, wenn das Formular manipuliert wurde, man sollte also mindestens noch validieren, ob der Wert größer 0 ist.

Wer auf AutoPostBack="true" nicht verzichten möchte, kann das auch ganz einfach haben:

<asp:Repeater ID="ListPaymentMethods" runat="server">
    <ItemTemplate>
         <input type="radio" name="paymentMethod" id="paymentMethod_<%# Eval("ID") %>" value="<%# Eval("ID") %>" onclick="__doPostBack('<%# BtnSelectPaymentMethod.UniqueID %>','')" />
    </ItemTemplate>
</asp:Repeater>

<asp:LinkButton ID="BtnSelectPaymentMethod" runat="server" OnClick="SelectPaymentMethod" Text="Wählen" Style="display:none" />

Der Trick ist simpel: abgefeuert wird immer der LinkButton, der nur dafür existiert, um uns das Event bereitzustellen. Wichtig: dieser darf nur mit CSS ausgeblendet werden, nicht mittels Visible="false". Denn Die Sicherheitsmechanismen von ASP.NET "merken" sofort, wenn ein Event für ein Element gefeuert werden soll, was gar nicht zum Client gerendert wurde. Das Ganze ist übrigens optional, denn wenn es einen allgemeinen Speichern-Button gibt, kann man auch diesen verwenden, sofern es die Logik hergibt.

Wichtig weiterhin:

Da es ja darum geht, dass das Ganze auch funktioniert, wenn kein JavaScript vom Client unterstützt wird, muss die Auswertung und Validierung zwingend im "abschließenden Event", also z.B. für einen Weiter- oder Speichern-Button stattfinden, man darf sich nicht auf das Event verlassen, was gefeuert wird, wenn die Radio-Button-Auswahl geändert wurde.



« Zurück  |  Weiter »