NumericTextBox control v ASP.NET

30. září 2004

Čas od času se stává, že je potřeba do formuláře vložit TextBox, který by přijímal jen čísla. Docílit toho se dá několika způsoby. Jedním z nich je napsat nový Server Control, který by dědil z původního TextBoxu.

NumericTextBox nebo ValidationControl? Potřebujeme-li vstup od uživatele, nikdy se nesmíme spolehnout na to, že bude odpovídat formátu, jaký požadujeme. Jedno ze základních pravidel při programování říká, že aplikace musí být „blbuvzdorná“. Pro webové aplikace to platí dvojnásob!

Pokud tedy chceme mít jistotu, že od uživatele dostaneme správnou hodnotu, máme v zásadě dva možné postupy. První z nich spoléhá na takzvané ValidationControls, které nám nabízí .NET Framework. Mají tu výhodu, že šetří hodně času programátora. Druhý způsob spočívá v tom, že uživateli vůbec nedovolíme (nebo mu to alespoň co nejvíce zkomplikujeme) zadat špatnou hodnotu. Je to sice trochu komplikovanější, ale pokud stejný problém řešíte po několikáté, určite se vyplatí pár řádků kódu navíc. V tomto článku si napíšeme jednoduchou třídu, která dědí z System.Web.UI.WebControls.TextBox, přinutíme ji však ignorovat jakýkoli jiný znak než číslici.

Pokud v HTML potřebujeme textové pole, které akceptuje pouze čísla, napíšeme zhruba toto:

<script>
  function EnsureNumeric()
  {
    var key = window.event.keyCode;
    if(key < 48 || key > 57)
      window.event.returnValue = false
  }
</script>
<input onkeypress=“EnsureNumeric()“ name=“numericbox“ type=“text“ />

Vycházíme z faktu, že kódy číslic jsou 48 až 57. Pokud se tedy uživatel pokusí do textboxu napsat cokoli jiného, jednoduše ho ingnorujeme. Čísla se také často zarovnávají k pravému okraji. Naše textové pole proto můžeme ještě vylepšit o atribut „dir“, který nastavíme na hodnotu „rtl“ (Right-to-Left), tedy dir="rtl". Zápis HTML budeme proto chtít mít zhruba v této podobě:

<input onkeypress=“EnsureNumeric()“ name=“numericbox“ type=“text“ dir=“rtl“/>

Cíl našeho snažení už známe. Teď tedy můžeme přejít k provedení. Pokud vložíme do ASP.NET formuláře TextBox a přidáme atribut „onkeypress“ takto…

<asp:TextBox id=“tbNr“ runat=“server“ onkeypress=“EnsureNumeric()“ />

…vyrenderuje se tento atribut do HTML beze změny. Stačí potom jen do stránky doplnit JavaScriptovou funkci EnsureNumeric() a je hotovo.

Pokud si ale chceme pro příště ušetřit ještě více práce, nabízí se nám další způsob – tvorba nové třídy. Nejdříve je potřeba vytvořit novou třídu, která bude dědit z původního „všeakceptujícího“ TextBoxu:

public class NumericTextBox : System.Web.UI.WebControls.TextBox

Všechno ponecháme beze změn, přepíšeme jen metodu Render a OnPreRender takto:

private string EnsureNumericScript = @“
<script>
  function EnsureNumeric(){
    var key = window.event.keyCode;
    if(key<48 || key>57)window.event.returnValue = false;
 &nbsp}
</script>“;
protected override void OnPreRender(EventArgs e)
{
  if (!Page.IsClientScriptBlockRegistered(„EnsureNumeric“))
  {
    Page.RegisterClientScriptBlock(„EnsureNumeric“, EnsureNumericScript);
  }
}
protected override void Render(HtmlTextWriter writer)
{
  writer.AddAttribute(„onkeypress“, „EnsureNumeric()“);
  base.Render(writer);
}

K původní metodě Render přidáme jen atrbibut onkeypress pro TextBox. V metodě OnPreRender zjistíme, jestli již náš javascript existuje. Pokud ne, vypíšeme ho z privátní proměnné EnusureNumericScript. Když pak příště budeme potřebovat umístit do formuláře textbox jen pro čísla, vystačíme si s následujícím zápisem a naše třída se pak o vše postará:

<ctl:NumericTextBox id=“nrtb“ runat=“server“ />

Na začátku jsem se ještě zmínil o atributu „dir“. Nový prvek o něj tedy také obohatíme. Třídu ještě rozšíříme o soukromou proměnnou dir a vlastnost Dir:

private string dir = „rtl“;
public string Dir
{
  get {return this.dir;}
  set {this.dir = value;}
}

Teď ještě doplníme vykreslení prvku o tento atribut:

writer.AddAttribute(„dir“, this.dir);

Vlastnost „dir“ je ve výchozím stavu nastavena na hodnotu „rtl“. Pokud tedy nevyžadujete zarovnání k levému okraji, můžete ji vynechat, v opačném případě by zápis vypadal takto:

<ctl:NumericTextBox id=“nrtb“ runat=“server“ Dir=“ltr“ />

Uvedený příklad by se dal ještě rozšiřovat a vylepšovat, můžete například začlenit podporu pro jiná než celá čísla a podobně. Tato úprava by spočívala ve změně schvalovací podmínky. Tečka má kód 46 (čárka 44), takže bychom ji tam jen šikovně začlenili. Vznikl by pak jiný problém. Museli bychom nějak testovat, jestli tam tečka (čárka či jiný oddělovač) již není. Můžete si například pohrát s controlem tak, že bude vždy po stisknutí tečky obsah textového pole procházet a nenarazí-li na žádnou jinou, vypíše ji. Jednodušší možnost je kontrolovat obsah až těsně před odesláním proti nějakému regulárnímu výrazu pomocí RegularExpressionValidatoru. To však už nechám na vás a vašich potřebách.

Ještě si neodpustím poznámku. Když použijete NumericTextBox, neznamená to, že můžete vynechat další způsoby kontroly. NumericTextBox jenom trochu vylepšuje uživatelův komfort tím, že se ho snaží držet v určitých mezích a nezdržuje ho dodatečnými poznámkami typu „někde nahoře jste zadal špatnou hodnotu“. Určitě byste měli hodnotu překontrolovat na serveru po odeslání, abyste měli stoprocentní jistotu, že se vám do zpracování nevloudil nějaký neočekávaný nesmysl.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek CSS pro zelenáče
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *