Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ There are a significant number of controls in ASP.NET Web Forms, and we will foc
- RadioButtonList
- Substitution
- Table
- TextBox
- [TextBox](docs/EditorControls/TextBox.md)
- View
- Xml
- Data Controls
Expand Down
202 changes: 202 additions & 0 deletions docs/EditorControls/TextBox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# TextBox

The **TextBox** component displays a single-line text box, multi-line text area, or specialized HTML5 input control (password, email, number, date, etc.) for user input.

Original Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.textbox?view=netframework-4.8

## Features Supported in Blazor

- Single-line text input (`<input type="text">`)
- Multi-line text area (`<textarea>`)
- Password input (`<input type="password">`)
- HTML5 input types (email, number, date, url, tel, etc.)
- Two-way data binding with `@bind-Text`
- MaxLength validation
- ReadOnly and Enabled/Disabled states
- Rows and Columns for sizing
- Placeholder text
- All style properties (BackColor, ForeColor, BorderColor, CssClass, Width, Height, etc.)
- TabIndex support

## Web Forms Features NOT Supported

- **AutoPostBack** - Not needed in Blazor; use event handlers instead
- **AutoComplete** - Handled by browser settings
- **TextChanged server event** - Use `@bind-Text` or `@onchange` event in Blazor
- **Wrap** - Use CSS styling instead

## Web Forms Declarative Syntax

```html
<asp:TextBox
AccessKey="string"
AutoCompleteType="None|Disabled|Search|FirstName|LastName|MiddleName|
NamePrefix|NameSuffix|FullName|Nickname|Email|HomePhone|WorkPhone|
CellPhone|HomeStreetAddress|HomeCity|HomeState|HomeZipCode|
HomeCountryRegion|WorkStreetAddress|WorkCity|WorkState|WorkZipCode|
WorkCountryRegion|Gender|Birthday|Occupation|BusinessUrl|
Company|Department|DisplayName|JobTitle|Notes"
AutoPostBack="True|False"
BackColor="color name|#dddddd"
BorderColor="color name|#dddddd"
BorderStyle="NotSet|None|Dotted|Dashed|Solid|Double|Groove|Ridge|
Inset|Outset"
BorderWidth="size"
Columns="integer"
CssClass="string"
Enabled="True|False"
Font-Bold="True|False"
Font-Italic="True|False"
Font-Names="string"
Font-Overline="True|False"
Font-Size="string|Smaller|Larger|XX-Small|X-Small|Small|Medium|
Large|X-Large|XX-Large"
Font-Strikeout="True|False"
Font-Underline="True|False"
ForeColor="color name|#dddddd"
Height="size"
ID="string"
MaxLength="integer"
OnTextChanged="TextChanged event handler"
Placeholder="string"
ReadOnly="True|False"
Rows="integer"
runat="server"
TabIndex="integer"
Text="string"
TextMode="SingleLine|MultiLine|Password|Color|Date|DateTime|
DateTimeLocal|Email|Month|Number|Range|Search|Phone|Time|Url|Week"
ToolTip="string"
Visible="True|False"
Width="size"
Wrap="True|False"
/>
```

## Blazor Razor Syntax

### Single-Line Text Input

```razor
<TextBox Text="Enter your name" CssClass="form-control" />
```

### Two-Way Data Binding

```razor
<TextBox @bind-Text="userName" />

@code {
private string userName = "John Doe";
}
```

### Password Input

```razor
<TextBox TextMode="TextBoxMode.Password" Placeholder="Enter password" />
```

### Multi-Line Text Area

```razor
<TextBox TextMode="TextBoxMode.MultiLine"
Rows="5"
Columns="40"
@bind-Text="comments" />
```

### HTML5 Input Types

```razor
<!-- Email -->
<TextBox TextMode="TextBoxMode.Email" Placeholder="email@example.com" />

<!-- Number -->
<TextBox TextMode="TextBoxMode.Number" />

<!-- Date -->
<TextBox TextMode="TextBoxMode.Date" />

<!-- URL -->
<TextBox TextMode="TextBoxMode.Url" Placeholder="https://example.com" />

<!-- Phone -->
<TextBox TextMode="TextBoxMode.Phone" Placeholder="(555) 123-4567" />
```

### ReadOnly and Disabled

```razor
<TextBox Text="Read only text" ReadOnly="true" />
<TextBox Text="Disabled text" Enabled="false" />
```

### With MaxLength Validation

```razor
<TextBox MaxLength="10" Placeholder="Max 10 characters" />
```

### Styled TextBox

```razor
<TextBox Text="Styled input"
BackColor="WebColor.LightYellow"
ForeColor="WebColor.Navy"
BorderColor="WebColor.Blue"
BorderWidth="Unit.Pixel(2)"
BorderStyle="BorderStyle.Solid"
Width="Unit.Pixel(300)" />
```

## HTML Output

### Single-Line TextBox
**Web Forms Input:**
```html
<asp:TextBox ID="txtName" Text="John" CssClass="form-control" runat="server" />
```

**Rendered HTML:**
```html
<input type="text" value="John" class="form-control" />
```

### Password TextBox
**Web Forms Input:**
```html
<asp:TextBox ID="txtPass" TextMode="Password" runat="server" />
```

**Rendered HTML:**
```html
<input type="password" />
```

### Multi-Line TextBox
**Web Forms Input:**
```html
<asp:TextBox ID="txtComments" TextMode="MultiLine" Rows="5" Columns="40" runat="server" />
```

**Rendered HTML:**
```html
<textarea rows="5" cols="40"></textarea>
```

## Migration Notes

When migrating from Web Forms to Blazor:

1. **Remove `runat="server"`** - Not needed in Blazor
2. **Remove `AutoPostBack`** - Use `@bind-Text` or event handlers
3. **Replace `OnTextChanged` with `@bind-Text`** - For real-time updates
4. **Update `TextMode` references** - Use `TextBoxMode.` enum prefix (e.g., `TextBoxMode.Password`)
5. **Use HTML5 input types** - Take advantage of new types like Email, Number, Date, etc.

## See Also

- [Label](Label.md) - Display static text
- [Button](Button.md) - Trigger actions
- [RequiredFieldValidator](../ValidationControls/RequiredFieldValidator.md) - Validate required fields
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ nav:
- Label: EditorControls/Label.md
- LinkButton: EditorControls/LinkButton.md
- Literal: EditorControls/Literal.md
- TextBox: EditorControls/TextBox.md
- RadioButton: EditorControls/RadioButton.md
- Data Controls:
- DataList: DataControls/DataList.md
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@page "/ControlSamples/TextBox"
@using BlazorWebFormsComponents.Enums

<h1>TextBox Samples</h1>

<h2>Single Line TextBox</h2>
<TextBox Text="@singleText" CssClass="form-control" />
<p>Value: @singleText</p>

<h2>Password TextBox</h2>
<TextBox TextMode="TextBoxMode.Password" Placeholder="Enter password" />

<h2>Email TextBox</h2>
<TextBox TextMode="TextBoxMode.Email" Placeholder="Enter email" />

<h2>Number TextBox</h2>
<TextBox TextMode="TextBoxMode.Number" Placeholder="Enter number" />

<h2>MultiLine TextBox</h2>
<TextBox TextMode="TextBoxMode.MultiLine" Rows="5" Columns="40" Text="@multiLineText" />
<p>Value: @multiLineText</p>

<h2>ReadOnly TextBox</h2>
<TextBox Text="Cannot edit this" ReadOnly="true" CssClass="form-control" />

<h2>Disabled TextBox</h2>
<TextBox Text="Disabled textbox" Enabled="false" CssClass="form-control" />

<h2>With MaxLength (10 characters max)</h2>
<TextBox MaxLength="10" Placeholder="Max 10 chars" CssClass="form-control" />

<h2>With Styles</h2>
<TextBox Text="Styled textbox"
BackColor="WebColor.LightYellow"
ForeColor="WebColor.Navy"
BorderColor="WebColor.Blue"
BorderWidth="Unit.Pixel(2)"
BorderStyle="BorderStyle.Solid"
Width="Unit.Pixel(200)" />

<h2>Date Picker</h2>
<TextBox TextMode="TextBoxMode.Date" />

<h2>URL Input</h2>
<TextBox TextMode="TextBoxMode.Url" Placeholder="Enter URL" />

@code {
private string singleText = "Default Text";
private string multiLineText = "Line 1\nLine 2\nLine 3";
}
30 changes: 30 additions & 0 deletions samples/BeforeWebForms/ControlSamples/TextBox/Default.aspx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<%@ Page Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html>
<html>
<head><title>TextBox Sample</title></head>
<body>
<form id="form1" runat="server">
<h2>Single Line TextBox</h2>
<asp:TextBox ID="txtSingle" Text="Default Text" CssClass="form-control" runat="server" />

<h2>Password TextBox</h2>
<asp:TextBox ID="txtPassword" TextMode="Password" runat="server" />

<h2>MultiLine TextBox</h2>
<asp:TextBox ID="txtMulti" TextMode="MultiLine" Rows="5" Columns="40" runat="server" />

<h2>ReadOnly TextBox</h2>
<asp:TextBox ID="txtReadOnly" Text="Cannot edit" ReadOnly="true" runat="server" />

<h2>Disabled TextBox</h2>
<asp:TextBox ID="txtDisabled" Text="Disabled" Enabled="false" runat="server" />

<h2>With MaxLength</h2>
<asp:TextBox ID="txtMaxLen" MaxLength="10" runat="server" />

<h2>With Styles</h2>
<asp:TextBox ID="txtStyled" BackColor="LightYellow" ForeColor="Navy"
BorderColor="Blue" BorderWidth="2" Width="200px" runat="server" />
</form>
</body>
</html>
70 changes: 70 additions & 0 deletions src/BlazorWebFormsComponents.Test/TextBox/Attributes.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
@using TBM = BlazorWebFormsComponents.Enums.TextBoxMode

@code {

[Fact]
public void TextBox_WithMaxLength_RendersMaxLengthAttribute()
{
// Arrange & Act
var cut = Render(@<TextBox MaxLength="10" />);

// Assert
var input = cut.Find("input");
input.GetAttribute("maxlength").ShouldBe("10");
}

[Fact]
public void TextBox_WithColumns_RendersSizeAttribute()
{
// Arrange & Act
var cut = Render(@<TextBox Columns="20" />);

// Assert
var input = cut.Find("input");
input.GetAttribute("size").ShouldBe("20");
}

[Fact]
public void TextBox_ReadOnly_RendersReadonlyAttribute()
{
// Arrange & Act
var cut = Render(@<TextBox ReadOnly="true" Text="Cannot edit" />);

// Assert
var input = cut.Find("input");
input.HasAttribute("readonly").ShouldBeTrue();
}

[Fact]
public void TextBox_Disabled_RendersDisabledAttribute()
{
// Arrange & Act
var cut = Render(@<TextBox Enabled="false" Text="Disabled" />);

// Assert
var input = cut.Find("input");
input.HasAttribute("disabled").ShouldBeTrue();
}

[Fact]
public void TextBox_WithTabIndex_RendersTabIndexAttribute()
{
// Arrange & Act
var cut = Render(@<TextBox TabIndex="5" />);

// Assert
var input = cut.Find("input");
input.GetAttribute("tabindex").ShouldBe("5");
}

[Fact]
public void TextBox_MultiLineWithMaxLength_DoesNotRenderMaxLength()
{
// Arrange & Act
var cut = Render(@<TextBox TextMode="TBM.MultiLine" MaxLength="100" />);

// Assert
var textarea = cut.Find("textarea");
textarea.HasAttribute("maxlength").ShouldBeFalse();
}
}
Loading
Loading