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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to this project will be documented in this file.

## [1.0.0] - 2025-05-25

### Added

- Improved README.md
- Added `minusComponent`, `plusComponent` inputs to set custom component template content to minus and plus buttons.
- Added `NgxInputCounterService` to set config.
- Added Standalone
- Upgraded to Angular 18

## [0.0.3]

### Added
Expand Down
124 changes: 123 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The input number with counter for Angular

| Angular | ngx-input-counter |
| -------- |:------:|
| >=16.0.0 | v1.0.x |
| >=15.0.0 | v0.0.x |

### Instalation
Expand All @@ -27,7 +28,7 @@ npm i ngx-input-counter

## Usage

Import the module
NgModule: Import the module

```typescript
import { NgxInputCounterModule } from 'ngx-input-counter';
Expand All @@ -40,6 +41,21 @@ import { NgxInputCounterModule } from 'ngx-input-counter';
})
```

Standalone: Import the component, optional: if you are using the directives

```ts
import { NgxInputCounterComponent } from 'ngx-input-counter';
@NgModule({
...
imports: [
...,
NgxInputCounterComponent,
PlusContentDirective,
MinusContentDirective,
],
})
```

Use in your components

```html
Expand All @@ -56,6 +72,8 @@ Use in your components
| step | `number` | `1` | Transition time for the animation |
| minusTemplate | `TemplateRef` | `-` | Pass a TemplateRef to replace the minus button content |
| plusTemplate | `TemplateRef` | `+` | Pass a TemplateRef to replace the plus button content |
| minusComponent | `Type` | `undefined` | Pass a Component to replace the minus button content |
| plusComponent | `Type` | `undefined` | Pass a Component to replace the plus button content |
| minusClass | `string` | `'ngx-input-counter-button'` | Classes of the minus button |
| plusClass | `string` | `'ngx-input-counter-button'` | Classes of the plus button |
| valueClass | `string` | `'ngx-input-counter-value'` | Classes of value text |
Expand Down Expand Up @@ -171,6 +189,110 @@ When you use the slot template you can pass classes to override the button class
</ng-template>
```

## Global Configuration

You can configure all `ngx-input-counter` components in your app using the `NgxInputCounterService` provider.
This allows you to set default values for all instances of `ngx-input-counter` throughout your application.

```ts
constructor (private config: NgxInputCounterService) {
this.config.min = 0
this.config.valueClass = 'p-2 border border-gray-400 font-monospace'
this.config.minusClass = 'btn border-gray-400 rounded-l-md opacity-50 hover:opacity-40'
this.config.plusClass = 'btn border-gray-400 rounded-r-md opacity-50 hover:opacity-40'
}
```

These settings will apply to all `ngx-input-counter` components in your application. However, you can still override individual values
directly through their input properties in your templates.

### Advanced Customization

For more advanced use cases, you can use the plusComponent and minusComponent properties to define custom components for the plus and minus buttons:

```ts
constructor (private config: NgxInputCounterService) {
...
this.config.minusComponent = MinusTemplateComponent;
this.config.plusComponent = PlusTemplateComponent;
}
```

This is useful when you have dynamic or reusable templates for your button content and want to configure them globally via the service.

### Extending the Component

Another powerful way to customize `ngx-input-counter` is by extending the `NgxInputCounterComponent` itself.
This allows you to create your own custom input counter component, add new properties, and directly modify the button content templates within your extended component.

```ts
@Component({
selector: 'app-input-counter',
standalone: true,
imports: [NgxInputCounterComponent],
template: `
<ng-template #plusTemplateIcon>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
</ng-template>
<ng-template #minusTemplateIcon let-step="step" let-min="min" let-value="value">
@if (value !== min + step) {
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15" />
</svg>
} @else {
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="#EF2F35">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
</svg>
}
</ng-template>
<ngx-input-counter class="custom-plus" style="margin: auto;"
[plusTemplate]="plusTemplateIcon"
[minusTemplate]="minusTemplateIcon"
[min]="min"
[max]="max"
[step]="step"
[value]="value"
[disabled]="disabled"
(change)="onInput($event)"
>
</ngx-input-counter>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AppCounterComponent),
multi: true
}
]
})
export class AppCounterComponent extends NgxInputCounterComponent {}
```

By creating your own component that extends the original, you can:

- Add custom inputs and behavior
- Override the button content templates
- Fully customize the appearance and functionality

You can then use `<app-input-counter>` instead of `<ngx-input-counter>` in your templates.

> ![NOTE]
> If you plan to use your extended component with Angular Forms, don't forget to provide the `NG_VALUE_ACCESSOR`

```ts
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AppCounterComponent),
multi: true
}
]
```

This ensures your custom counter component works properly with ngModel or reactive forms.

## Development

Clone this repo and install the dependencies. Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
Expand Down
38 changes: 18 additions & 20 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,21 @@
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/demo",
"index": "projects/demo/src/index.html",
"main": "projects/demo/src/main.ts",
"browser": "projects/demo/src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "projects/demo/tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"projects/demo/src/favicon.ico",
"projects/demo/src/assets"
{
"glob": "**/*",
"input": "projects/demo/public"
}
],
"styles": [
"projects/demo/src/styles.scss"
Expand All @@ -72,24 +74,21 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumWarning": "500kB",
"maximumError": "1MB"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
"maximumWarning": "2kB",
"maximumError": "4kB"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
"sourceMap": true
}
},
"defaultConfiguration": "production"
Expand All @@ -98,19 +97,16 @@
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "demo:build:production"
"buildTarget": "demo:build:production"
},
"development": {
"browserTarget": "demo:build:development"
"buildTarget": "demo:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "demo:build"
}
"builder": "@angular-devkit/build-angular:extract-i18n"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
Expand All @@ -122,8 +118,10 @@
"tsConfig": "projects/demo/tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": [
"projects/demo/src/favicon.ico",
"projects/demo/src/assets"
{
"glob": "**/*",
"input": "projects/demo/public"
}
],
"styles": [
"projects/demo/src/styles.scss"
Expand Down
Loading