KTUIKTUI
KTUIKTUI
ComponentsDocsStudio

Getting Started

IntroductionInstallationApproachThemingJavaScriptTypeScriptDark modeRTLReferencesChangelog - v1.2.5Metronic TemplatePopular

Components

AccordionAvatarAlertBadgeBreadcrumbButtonCardCarouselNewClipboardNewCheckboxCollapseDatatableUpdateContext MenuNewDismissDrawerDropdownImage InputInputInput numberNewKbdLinkModalPaginationPin inputNewProgressRadio GroupRange SliderNewRatingNewReparentRepeaterNewScrollableScrollspyScrolltoSelectSeparatorSkeletonStepperStickySwitchTabsTextareaTheme SwitchToastTooltipToggleToggle GroupToggle PasswordTooltip
©2026 KtUI. All rights reserved.
A project by Keenthemes
Docs
Input number

Input number

Numeric field with KtUI lifecycle on the native input[type=number], optional decrement/increment buttons, and custom events. Not the wizard Stepper—see Stepper for multi-step flows.

Examples

Basic

Initialize on a wrapper that contains one input[type="number"], or put data-kt-input-number on the input itself.

<div class="w-full max-w-xs" data-kt-input-number="true">
  <input
    type="number"
    class="kt-input w-full tabular-nums"
    min="0"
    max="99"
    step="1"
    value="1"
  />
</div>

Min, max, and step

Use native min, max, and step on the number input. Optional + / − controls use the browser’s stepUp() / stepDown() so behavior matches native constraints.

<div class="w-full max-w-xs space-y-2" data-kt-input-number="true">
  <label for="kt-in-demo-step" class="text-sm text-muted-foreground"
    >Quantity (step 5, max 50)</label
  ><input
    id="kt-in-demo-step"
    type="number"
    class="kt-input w-full tabular-nums"
    min="0"
    max="50"
    step="5"
    value="10"
  />
  <p class="text-xs text-muted-foreground">
    Native <code class="text-foreground/80">min</code>,<!-- -->
    <code class="text-foreground/80">max</code>, and<!-- -->
    <code class="text-foreground/80">step</code> apply to typing and spinners.
  </p>
</div>

With buttons

Pair data-kt-input-number-decrement and data-kt-input-number-increment with accessible names (aria-label or visible text) on the buttons.

<div class="kt-input-group w-full max-w-xs" data-kt-input-number="true">
  <button
    type="button"
    class="kt-btn kt-btn-outline shrink-0 px-3"
    data-kt-input-number-decrement="true"
    aria-label="Decrease quantity"
  >
    −</button
  ><input
    type="number"
    class="kt-input min-w-0 tabular-nums text-center"
    min="0"
    max="10"
    step="1"
    aria-label="Quantity"
    value="5"
  /><button
    type="button"
    class="kt-btn kt-btn-outline shrink-0 px-3"
    data-kt-input-number-increment="true"
    aria-label="Increase quantity"
  >
    +
  </button>
</div>

Disabled

Use the native disabled attribute on the input. Decrement/increment handlers no-op while disabled.

<div class="w-full max-w-xs space-y-2" data-kt-input-number="true">
  <input
    type="number"
    class="kt-input w-full opacity-80 tabular-nums"
    min="0"
    max="10"
    disabled=""
    value="3"
  />
  <p class="text-xs text-muted-foreground">
    Native <code class="text-foreground/80">disabled</code> —
    increment/decrement hooks are ignored.
  </p>
</div>

Usage

Wrapper root

<div data-kt-input-number>
  <input type="number" min="0" max="99" step="1" value="1" class="kt-input" />
</div>

Input root

<input type="number" min="0" max="10" value="3" data-kt-input-number class="kt-input" />

If a wrapper contains more than one number input, the component binds to the first in tree order (avoid multiple fields per instance).

Optional buttons

Use kt-input-group so decrement/increment controls share one edge with the field and match the input height (items-stretch on the group). The group stylesheet squares the inner corners of outline buttons next to a kt-input (and removes their side shadow) so the join matches the addon pattern—no extra radius utilities on the minus button are required.

<div data-kt-input-number class="kt-input-group w-full max-w-xs">
  <button type="button" class="kt-btn kt-btn-outline px-3" data-kt-input-number-decrement aria-label="Decrease">
    −
  </button>
  <input type="number" min="0" max="10" step="1" value="5" class="kt-input text-center" />
  <button type="button" class="kt-btn kt-btn-outline px-3" data-kt-input-number-increment aria-label="Increase">
    +
  </button>

Component API

Options

NameTypeDefaultDescription
data-kt-input-numberflag—Enables auto-init on the element.
data-kt-input-number-lazyboolean

min, max, step, and value use the native attributes on input[type="number"].

Methods

MethodDescription
new KTInputNumber(element, options?)Creates an instance if markup includes a number input.
getNumberInput()Returns the controlled HTMLInputElement or null.
getValue()Parsed numeric value, or when empty / non-finite.

Static methods

MethodDescription
KTInputNumber.init()Initializes [data-kt-input-number] (except lazy).
KTInputNumber.createInstances()Same discovery; safe to call after DOM updates.
KTInputNumber.getInstance(element)Returns the instance on the root, or null.
KTInputNumber.init();
 
const el = document.querySelector('[data-kt-input-number]');
const num = KTInputNumber.getInstance(el);
console.log(num?.getValue());

Events

Native input and change on the number control still fire. KtUI dispatches:

EventWhenevent.detail.payload
kt.input-number.inputNative input{ value, valueAsString, min?, max?, step? } — value is null when empty; step omitted when step="any".
kt.input-number.change
root.addEventListener('kt.input-number.change', (e) => {
  console.log(e.detail.payload.value, e.detail.payload.valueAsString);
});

Accessibility

Focus, spin buttons (where the browser provides them), and validation come from the native input[type="number"]. Keep the real input in the tab order. When using custom + / − buttons, give each an aria-label (or visible text) and avoid disabling focus to the input unless the whole control is disabled.

TypeScript

import {
  KTInputNumber,
  type KTInputNumberConfigInterface,
  type KTInputNumberEventPayloadInterface,
  type KTInputNumberInterface,
} from '@keenthemes/ktui';
 
const root = document.querySelector<HTMLElement>('[data-kt-input-number]');
if (!root) {
  throw new Error('missing root');
}
 
const widget: KTInputNumberInterface | null =
  KTInputNumber.getOrCreateInstance(root, {} satisfies KTInputNumberConfigInterface);
 
if (widget) {
  const input = widget.





PreviouseInputNextKbd

On This Page

  • Examples
    • Basic
    • Min, max, and step
    • With buttons
    • Disabled
  • Usage
    • Wrapper root
    • Input root
    • Optional buttons
  • Component API
    • Options
    • Methods
    • Static methods
    • Events
  • Accessibility
  • TypeScript
</div>
false
Skip auto-init; use getOrCreateInstance or new KTInputNumber(...).
data-kt-input-number-decrementflag—Button (or activatable element) that calls stepDown() on the controlled input.
data-kt-input-number-incrementflag—Button that calls stepUp() on the controlled input.
null
getOption(name)Option from merged config / data attributes.
getElement()Root element (wrapper or the input).
on / offInstance callback map (see Events).
dispose()Removes listeners and clears the instance from KTData.
KTInputNumber.getOrCreateInstance(element, config?)Returns an instance or null if no number input exists.
Native change
Same shape as input
getNumberInput
();
const payload: KTInputNumberEventPayloadInterface = {
value: widget.getValue(),
valueAsString: input?.value ?? '',
};
console.log(payload);
}