@* EN: 6-digit OTP input with auto-focus, auto-advance, and backspace support. VI: Input OTP 6 chữ số với auto-focus, tự chuyển ô, và hỗ trợ backspace. *@ @inject IJSRuntime JS
@for (int i = 0; i < DigitCount; i++) { var index = i; }
@code { private string[] _digits = new string[6]; /// /// EN: Number of OTP digits. /// VI: Số chữ số OTP. /// [Parameter] public int DigitCount { get; set; } = 6; /// /// EN: Use blue theme (for 2FA authenticator). /// VI: Dùng theme xanh dương (cho 2FA authenticator). /// [Parameter] public bool UseBlueTheme { get; set; } /// /// EN: Accessible group label for screen readers. /// VI: Nhãn nhóm accessible cho screen reader. /// [Parameter] public string GroupAriaLabel { get; set; } = "Enter OTP code"; /// /// EN: Callback when all digits are entered. /// VI: Callback khi tất cả chữ số được nhập. /// [Parameter] public EventCallback OnComplete { get; set; } protected override void OnInitialized() { _digits = new string[DigitCount]; } private async Task HandleInput(ChangeEventArgs e, int index) { var value = e.Value?.ToString() ?? ""; // EN: Only allow numeric input // VI: Chỉ cho phép nhập số if (!string.IsNullOrEmpty(value) && !char.IsDigit(value[0])) { _digits[index] = ""; return; } _digits[index] = value; if (!string.IsNullOrEmpty(value) && index < DigitCount - 1) { // EN: Auto-advance to next input // VI: Tự động chuyển sang ô tiếp theo await JS.InvokeVoidAsync("focusOtpInput", index + 1); } // EN: Check if all digits are filled // VI: Kiểm tra tất cả ô đã nhập xong chưa if (_digits.All(d => !string.IsNullOrEmpty(d))) { var code = string.Join("", _digits); await OnComplete.InvokeAsync(code); } } private async Task HandleKeyDown(KeyboardEventArgs e, int index) { if (e.Key == "Backspace" && string.IsNullOrEmpty(_digits[index]) && index > 0) { // EN: Move to previous input on backspace // VI: Chuyển về ô trước khi nhấn backspace _digits[index - 1] = ""; await JS.InvokeVoidAsync("focusOtpInput", index - 1); } } }