https://github.com/istvan-ujjmeszaros/touchspin-angular
https://github.com/istvan-ujjmeszaros/touchspin-angular
Last synced: 10 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/istvan-ujjmeszaros/touchspin-angular
- Owner: istvan-ujjmeszaros
- License: other
- Created: 2025-10-15T00:06:59.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2025-10-24T04:09:55.000Z (3 months ago)
- Last Synced: 2025-12-26T21:10:21.226Z (about 1 month ago)
- Language: TypeScript
- Size: 479 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
- fucking-awesome-angular - touchspin-angular - Angular adapter for the <b><code> 504⭐</code></b> <b><code> 155🍴</code></b> [TouchSpin](https://github.com/istvan-ujjmeszaros/touchspin)) number input component with per-renderer support. (Third Party Components / Form Controls)
- awesome-angular - touchspin-angular - Angular adapter for the [TouchSpin](https://github.com/istvan-ujjmeszaros/touchspin) number input component with per-renderer support. (Third Party Components / Form Controls)
README
# TouchSpin Angular
Angular adapter for TouchSpin numeric input spinner - Native Angular components with full framework integration.
## Features
- Native Angular components with ControlValueAccessor
- Reactive and template-driven forms support
- Per-renderer subpath imports (Bootstrap 3/4/5, Tailwind, Vanilla)
- Standalone components (Angular 14+)
- SSR/Angular Universal compatible
- Full keyboard navigation and ARIA attributes
- Comprehensive test coverage
- Complete TouchSpin API support
## Installation
```bash
npm install @touchspin/angular @touchspin/core @touchspin/renderer-bootstrap5
# or
yarn add @touchspin/angular @touchspin/core @touchspin/renderer-bootstrap5
# or
pnpm add @touchspin/angular @touchspin/core @touchspin/renderer-bootstrap5
```
## Quick Start
```typescript
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
import '@touchspin/renderer-vanilla/css';
@Component({
selector: 'app-root',
standalone: true,
imports: [FormsModule, TouchSpinVanillaComponent],
template: `
Value: {{ value }}
`
})
export class AppComponent {
value = 25;
}
```
## Available Renderers
Choose the renderer that matches your design system:
| Renderer | Import | CSS Import | Description |
|----------|--------|------------|-------------|
| **Vanilla** | `@touchspin/angular/vanilla` | `@touchspin/renderer-vanilla/css` | Clean, framework-free styling |
| **Bootstrap 5** | `@touchspin/angular/bootstrap5` | `@touchspin/renderer-bootstrap5/css` | Bootstrap 5 compatible |
| **Bootstrap 4** | `@touchspin/angular/bootstrap4` | `@touchspin/renderer-bootstrap4/css` | Bootstrap 4 compatible |
| **Bootstrap 3** | `@touchspin/angular/bootstrap3` | `@touchspin/renderer-bootstrap3/css` | Bootstrap 3 compatible |
| **Tailwind** | `@touchspin/angular/tailwind` | `@touchspin/renderer-tailwind/css` | Tailwind CSS styling |
## API Reference
### Inputs (Properties)
#### Value Management
```typescript
```
#### Configuration
```typescript
```
#### State & Behavior
```typescript
```
#### Form Integration
```typescript
```
#### Styling
```typescript
```
#### Events
```typescript
```
### Imperative API (ViewChild)
```typescript
import { Component, ViewChild } from '@angular/core';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-example',
template: `
+1
`
})
export class ExampleComponent {
@ViewChild('touchSpinRef') touchSpin!: TouchSpinVanillaComponent;
increment() {
this.touchSpin.increment();
}
}
```
#### TouchSpinHandle Methods
```typescript
interface TouchSpinHandle {
// Focus Management
focus(): void; // Focus the input
blur(): void; // Blur the input
// Value Control
increment(): void; // Increment by step
decrement(): void; // Decrement by step
getValue(): number; // Get current value
setValue(value: number): void; // Set new value
// Continuous Spinning
startUpSpin(): void; // Start continuous upward spinning
startDownSpin(): void; // Start continuous downward spinning
stopSpin(): void; // Stop any continuous spinning
// Configuration
updateSettings(opts: Partial): void;
// Update settings at runtime
}
```
## Usage Examples
### Basic Controlled Component
```typescript
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-basic',
standalone: true,
imports: [FormsModule, TouchSpinVanillaComponent],
template: `
Value: {{ value }}
`
})
export class BasicComponent {
value = 25;
}
```
### With Prefix/Suffix
```typescript
import { Component } from '@angular/core';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-currency',
standalone: true,
imports: [TouchSpinVanillaComponent],
template: `
`
})
export class CurrencyComponent {
price = 29.99;
}
```
### Event Handling
```typescript
import { Component } from '@angular/core';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-events',
standalone: true,
imports: [TouchSpinVanillaComponent],
template: `
Event Log:
- {{ event }}
`
})
export class EventsComponent {
events: string[] = [];
addEvent(message: string) {
this.events.unshift(`${new Date().toLocaleTimeString()}: ${message}`);
}
trackByIndex(index: number) {
return index;
}
}
```
### Imperative Control
```typescript
import { Component, ViewChild } from '@angular/core';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-imperative',
standalone: true,
imports: [TouchSpinVanillaComponent],
template: `
Set to 42
Start Spinning Up
Stop Spinning
Show Current Value
Current value: {{ currentValue }}
`
})
export class ImperativeComponent {
@ViewChild('touchSpin') touchSpin!: TouchSpinVanillaComponent;
currentValue = 0;
setValue42() {
this.touchSpin.setValue(42);
}
startSpinning() {
this.touchSpin.startUpSpin();
}
stopSpinning() {
this.touchSpin.stopSpin();
}
showValue() {
this.currentValue = this.touchSpin.getValue();
}
}
```
### Reactive Forms
```typescript
import { Component } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, FormGroup } from '@angular/forms';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-reactive',
standalone: true,
imports: [ReactiveFormsModule, TouchSpinVanillaComponent],
template: `
Quantity:
Add to Cart
`
})
export class ReactiveComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
quantity: [1]
});
}
onSubmit() {
console.log('Quantity:', this.form.value.quantity);
}
}
```
## Advanced Configuration
### Custom Core Options
```typescript
import { Component } from '@angular/core';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
@Component({
selector: 'app-advanced',
standalone: true,
imports: [TouchSpinVanillaComponent],
template: `
`
})
export class AdvancedComponent {}
```
## Testing
```typescript
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { TouchSpinVanillaComponent } from '@touchspin/angular/vanilla';
describe('TouchSpinComponent', () => {
let component: TestComponent;
let fixture: ComponentFixture;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FormsModule, TouchSpinVanillaComponent, TestComponent]
}).compileComponents();
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should increment value', () => {
const touchSpin = fixture.nativeElement.querySelector('touch-spin');
const incrementBtn = touchSpin.querySelector('button:last-child');
incrementBtn.click();
fixture.detectChanges();
expect(component.value).toBe(6);
});
});
@Component({
selector: 'test-component',
template: ''
})
class TestComponent {
value = 5;
}
```
## Development
```bash
# Install dependencies
yarn install
# Build all packages
yarn build
# Run tests
yarn test
# Run tests with coverage
yarn test:coverage
# Run tests in watch mode
yarn test:watch
# Type checking
yarn typecheck
# Linting
yarn lint
```
## Related Packages
### Core
- **@touchspin/core** - Core TouchSpin logic and API
### Renderers
- **@touchspin/renderer-vanilla** - Vanilla CSS renderer
- **@touchspin/renderer-bootstrap3** - Bootstrap 3 renderer
- **@touchspin/renderer-bootstrap4** - Bootstrap 4 renderer
- **@touchspin/renderer-bootstrap5** - Bootstrap 5 renderer
- **@touchspin/renderer-tailwind** - Tailwind CSS renderer
### Adapters
- **@touchspin/angular** - Angular adapter (this package)
- **@touchspin/react** - React adapter
- **@touchspin/jquery** - jQuery plugin
- **@touchspin/webcomponent** - Web Components
- **@touchspin/standalone** - Standalone bundle
## Contributing
Contributions welcome! Please see the [main TouchSpin repository](https://github.com/istvan-ujjmeszaros/touchspin) for [contribution guidelines](https://github.com/istvan-ujjmeszaros/touchspin/blob/main/CONTRIBUTING.md).
## License
MIT © Istvan Ujj-Meszaros