ngx-promise-buttons 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +127 -0
- package/fesm2022/ngx-promise-buttons.mjs +261 -0
- package/fesm2022/ngx-promise-buttons.mjs.map +1 -0
- package/package.json +38 -0
- package/types/ngx-promise-buttons.d.ts +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Johannes Millan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<p align="center"><img src="logo.png"></p>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://badge.fury.io/js/ngx-promise-buttons">
|
|
5
|
+
<img src="https://camo.githubusercontent.com/5e39de25cca817826da9e93cdce01f16bc499695/68747470733a2f2f62616467652e667572792e696f2f6a732f616e67756c6172322d70726f6d6973652d627574746f6e732e737667"
|
|
6
|
+
alt="npm version"></a>
|
|
7
|
+
<a href="https://travis-ci.org/meysamsahragard/ngx-promise-buttons?branch=master">
|
|
8
|
+
<img src="https://camo.githubusercontent.com/849a28d2647af8a0fe2a8d47b860d638f5421948/68747470733a2f2f7472617669732d63692e6f72672f6a6f68616e6e65736a6f2f616e67756c6172322d70726f6d6973652d627574746f6e732e737667"
|
|
9
|
+
alt="Build Status"></a>
|
|
10
|
+
<a href="https://coveralls.io/github/meysamsahragard/ngx-promise-buttons?branch=master">
|
|
11
|
+
<img src="https://camo.githubusercontent.com/80cb53bf16882ebc70866dffd299edfa741b26e9/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6a6f68616e6e65736a6f2f616e67756c6172322d70726f6d6973652d627574746f6e732f62616467652e7376673f6272616e63683d6d6173746572"
|
|
12
|
+
alt="Coverage Status"></a>
|
|
13
|
+
<a href="https://lbesson.mit-license.org">
|
|
14
|
+
<img alt="MIT license"
|
|
15
|
+
src="https://camo.githubusercontent.com/311762166ef25238116d3cadd22fcb6091edab98/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75652e737667">
|
|
16
|
+
</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
*ngx-promise-buttons* is a simple module that let's you add a loading indicator to a button of your choice. Check out the [demo](http://meysamsahragard.github.io/ngx-promise-buttons/#demo)!
|
|
21
|
+
|
|
22
|
+
[Bug-reports or feature request](https://github.com/meysamsahragard/ngx-promise-buttons/issues) as well as any other kind of **feedback is highly welcome!**
|
|
23
|
+
|
|
24
|
+
## Getting started
|
|
25
|
+
Install it via npm:
|
|
26
|
+
```
|
|
27
|
+
npm install ngx-promise-buttons -S
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
And add it as a dependency to your main module
|
|
31
|
+
```typescript
|
|
32
|
+
import {NgxPromiseButtonModule} from 'ngx-promise-buttons';
|
|
33
|
+
|
|
34
|
+
@NgModule({
|
|
35
|
+
imports: [
|
|
36
|
+
NgxPromiseButtonModule.forRoot(),
|
|
37
|
+
],
|
|
38
|
+
})
|
|
39
|
+
export class MainAppModule {
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
Using the buttons is easy. Just pass a promise to the directive:
|
|
43
|
+
```html
|
|
44
|
+
<button (click)="someAction()"
|
|
45
|
+
[promiseBtn]="promiseSetBySomeAction">Click me to spin!</button>
|
|
46
|
+
```
|
|
47
|
+
```typescript
|
|
48
|
+
export class SomeComponent {
|
|
49
|
+
// some example async action, but this works with any promise
|
|
50
|
+
someAction(){
|
|
51
|
+
this.promiseSetBySomeAction = new Promise((resolve, reject) => {
|
|
52
|
+
setTimeout(resolve, 2000);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Styling the button
|
|
60
|
+
To give you maximum flexibility there are no base styles coming with the directive, but it is easy to fix that! There are lots of free css-spinners out there. Just find one of your liking and add the css to your global stylesheet.
|
|
61
|
+
|
|
62
|
+
**Ressources:**
|
|
63
|
+
* http://cssload.net/
|
|
64
|
+
* http://projects.lukehaas.me/css-loaders/
|
|
65
|
+
* http://tobiasahlin.com/spinkit/
|
|
66
|
+
|
|
67
|
+
There are selectors you can use to style. There is the `.is-loading` class on the button, which is set, when the promise is pending and there is the `<span class="btn-spinner"></span>` element inside the button.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
Configuration is done via the forRoot method of the promise button module:
|
|
72
|
+
```typescript
|
|
73
|
+
import {NgxPromiseButtonModule} from 'ngx-promise-buttons';
|
|
74
|
+
|
|
75
|
+
@NgModule({
|
|
76
|
+
imports: [
|
|
77
|
+
NgxPromiseButtonModule
|
|
78
|
+
.forRoot({
|
|
79
|
+
// your custom config goes here
|
|
80
|
+
spinnerTpl: '<span class="btn-spinner"></span>',
|
|
81
|
+
// disable buttons when promise is pending
|
|
82
|
+
disableBtn: true,
|
|
83
|
+
// the class used to indicate a pending promise
|
|
84
|
+
btnLoadingClass: 'is-loading',
|
|
85
|
+
// only disable and show is-loading class for clicked button,
|
|
86
|
+
// even when they share the same promise
|
|
87
|
+
handleCurrentBtnOnly: false,
|
|
88
|
+
}),
|
|
89
|
+
],
|
|
90
|
+
})
|
|
91
|
+
export class MainAppModule {
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Using observables
|
|
96
|
+
When you're using the module with observables make sure to pass a subscription to the directive rather than an observable directly.
|
|
97
|
+
```typescript
|
|
98
|
+
const FAKE_FACTORY = {
|
|
99
|
+
initObservable: (): Observable<number> => {
|
|
100
|
+
return new Observable(observer => {
|
|
101
|
+
setTimeout(() => {
|
|
102
|
+
observer.complete();
|
|
103
|
+
}, 4000);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// DO:
|
|
109
|
+
const observable = FAKE_FACTORY.initObservable();
|
|
110
|
+
this.passedToDirective = observable.subscribe(
|
|
111
|
+
// ...
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// DON'T DO:
|
|
115
|
+
const observable = FAKE_FACTORY.initObservable();
|
|
116
|
+
this.passedToDirective = observable;
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Using booleans
|
|
121
|
+
Is now also possible.
|
|
122
|
+
```html
|
|
123
|
+
<button (click)="someAction()"
|
|
124
|
+
[promiseBtn]="isShowBoolean">Click!</button>
|
|
125
|
+
```
|
|
126
|
+
## Contributing
|
|
127
|
+
Contribution guidelines: [CONTRIBUTING.md](https://github.com/meysamsahragard/ngx-promise-buttons/blob/master/CONTRIBUTING.md)
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, HostListener, Input, Inject, Directive, NgModule } from '@angular/core';
|
|
3
|
+
import { Observable, Subscription } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_CFG = {
|
|
6
|
+
spinnerTpl: '<span class="btn-spinner"></span>',
|
|
7
|
+
disableBtn: true,
|
|
8
|
+
btnLoadingClass: 'is-loading',
|
|
9
|
+
handleCurrentBtnOnly: false,
|
|
10
|
+
minDuration: null,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const userCfg = new InjectionToken('cfg');
|
|
14
|
+
|
|
15
|
+
class PromiseBtnDirective {
|
|
16
|
+
// this is added to fix the overriding of the disabled state by the loading indicator button.
|
|
17
|
+
set isDisabledFromTheOutsideSetter(v) {
|
|
18
|
+
this.isDisabledFromTheOutside = v;
|
|
19
|
+
if (v) {
|
|
20
|
+
// disabled means always disabled
|
|
21
|
+
this.btnEl.setAttribute('disabled', 'disabled');
|
|
22
|
+
}
|
|
23
|
+
else if (this.isPromiseDone || this.isPromiseDone === undefined) {
|
|
24
|
+
this.btnEl.removeAttribute('disabled');
|
|
25
|
+
}
|
|
26
|
+
// else the button is loading, so do not change the disabled loading state.
|
|
27
|
+
}
|
|
28
|
+
constructor(el, cfg) {
|
|
29
|
+
// provide configuration
|
|
30
|
+
this.cfg = Object.assign({}, DEFAULT_CFG, cfg);
|
|
31
|
+
// save element
|
|
32
|
+
this.btnEl = el.nativeElement;
|
|
33
|
+
}
|
|
34
|
+
set promiseBtn(passedValue) {
|
|
35
|
+
const isObservable = passedValue instanceof Observable;
|
|
36
|
+
const isSubscription = passedValue instanceof Subscription;
|
|
37
|
+
const isBoolean = typeof passedValue === 'boolean';
|
|
38
|
+
const isPromise = passedValue instanceof Promise || (passedValue !== null &&
|
|
39
|
+
typeof passedValue === 'object' &&
|
|
40
|
+
typeof passedValue.then === 'function' &&
|
|
41
|
+
typeof passedValue.catch === 'function');
|
|
42
|
+
if (isObservable) {
|
|
43
|
+
throw new TypeError('promiseBtn must be an instance of Subscription, instance of Observable given');
|
|
44
|
+
}
|
|
45
|
+
else if (isSubscription) {
|
|
46
|
+
const sub = passedValue;
|
|
47
|
+
if (!sub.closed) {
|
|
48
|
+
this.promise = new Promise((resolve) => {
|
|
49
|
+
sub.add(resolve);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (isPromise) {
|
|
54
|
+
this.promise = passedValue;
|
|
55
|
+
}
|
|
56
|
+
else if (isBoolean) {
|
|
57
|
+
this.promise = this.createPromiseFromBoolean(passedValue);
|
|
58
|
+
}
|
|
59
|
+
this.checkAndInitPromiseHandler(this.btnEl);
|
|
60
|
+
}
|
|
61
|
+
ngAfterContentInit() {
|
|
62
|
+
this.prepareBtnEl(this.btnEl);
|
|
63
|
+
// trigger changes once to handle initial promises
|
|
64
|
+
this.checkAndInitPromiseHandler(this.btnEl);
|
|
65
|
+
}
|
|
66
|
+
ngOnDestroy() {
|
|
67
|
+
// cleanup
|
|
68
|
+
if (this.minDurationTimeout) {
|
|
69
|
+
clearTimeout(this.minDurationTimeout);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
createPromiseFromBoolean(val) {
|
|
73
|
+
if (val) {
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
this._fakePromiseResolve = resolve;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
if (this._fakePromiseResolve) {
|
|
80
|
+
this._fakePromiseResolve();
|
|
81
|
+
}
|
|
82
|
+
return this.promise;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Initializes all html and event handlers
|
|
87
|
+
*/
|
|
88
|
+
prepareBtnEl(btnEl) {
|
|
89
|
+
// handle promises passed via promiseBtn attribute
|
|
90
|
+
this.appendSpinnerTpl(btnEl);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Checks if all required parameters are there and inits the promise handler
|
|
94
|
+
*/
|
|
95
|
+
checkAndInitPromiseHandler(btnEl) {
|
|
96
|
+
// check if element and promise is set
|
|
97
|
+
if (btnEl && this.promise) {
|
|
98
|
+
this.initPromiseHandler(btnEl);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Helper FN to add class
|
|
103
|
+
*/
|
|
104
|
+
addLoadingClass(el) {
|
|
105
|
+
if (typeof this.cfg.btnLoadingClass === 'string') {
|
|
106
|
+
el.classList.add(this.cfg.btnLoadingClass);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Helper FN to remove classes
|
|
111
|
+
*/
|
|
112
|
+
removeLoadingClass(el) {
|
|
113
|
+
if (typeof this.cfg.btnLoadingClass === 'string') {
|
|
114
|
+
el.classList.remove(this.cfg.btnLoadingClass);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handles everything to be triggered when the button is set
|
|
119
|
+
* to loading state.
|
|
120
|
+
*/
|
|
121
|
+
initLoadingState(btnEl) {
|
|
122
|
+
this.addLoadingClass(btnEl);
|
|
123
|
+
this.disableBtn(btnEl);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Handles everything to be triggered when loading is finished
|
|
127
|
+
*/
|
|
128
|
+
cancelLoadingStateIfPromiseAndMinDurationDone(btnEl) {
|
|
129
|
+
if ((!this.cfg.minDuration || this.isMinDurationTimeoutDone) && this.isPromiseDone) {
|
|
130
|
+
this.removeLoadingClass(btnEl);
|
|
131
|
+
this.enableBtn(btnEl);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
disableBtn(btnEl) {
|
|
135
|
+
if (this.cfg.disableBtn) {
|
|
136
|
+
btnEl.setAttribute('disabled', 'disabled');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
enableBtn(btnEl) {
|
|
140
|
+
if (this.cfg.disableBtn) {
|
|
141
|
+
if (this.isDisabledFromTheOutside) {
|
|
142
|
+
btnEl.setAttribute('disabled', 'disabled');
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
btnEl.removeAttribute('disabled');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Initializes a watcher for the promise. Also takes
|
|
151
|
+
* this.cfg.minDuration into account if given.
|
|
152
|
+
*/
|
|
153
|
+
initPromiseHandler(btnEl) {
|
|
154
|
+
const promise = this.promise;
|
|
155
|
+
// watch promise to resolve or fail
|
|
156
|
+
this.isMinDurationTimeoutDone = false;
|
|
157
|
+
this.isPromiseDone = false;
|
|
158
|
+
// create timeout if option is set
|
|
159
|
+
if (this.cfg.minDuration) {
|
|
160
|
+
this.minDurationTimeout = window.setTimeout(() => {
|
|
161
|
+
this.isMinDurationTimeoutDone = true;
|
|
162
|
+
this.cancelLoadingStateIfPromiseAndMinDurationDone(btnEl);
|
|
163
|
+
}, this.cfg.minDuration);
|
|
164
|
+
}
|
|
165
|
+
const resolveLoadingState = () => {
|
|
166
|
+
this.isPromiseDone = true;
|
|
167
|
+
this.cancelLoadingStateIfPromiseAndMinDurationDone(btnEl);
|
|
168
|
+
};
|
|
169
|
+
if (!this.cfg.handleCurrentBtnOnly) {
|
|
170
|
+
this.initLoadingState(btnEl);
|
|
171
|
+
}
|
|
172
|
+
// native Promise doesn't have finally
|
|
173
|
+
if (promise.finally) {
|
|
174
|
+
promise.finally(resolveLoadingState);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
promise
|
|
178
|
+
.then(resolveLoadingState)
|
|
179
|
+
.catch(resolveLoadingState);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* $compile and append the spinner template to the button.
|
|
184
|
+
*/
|
|
185
|
+
appendSpinnerTpl(btnEl) {
|
|
186
|
+
// TODO add some kind of compilation later on
|
|
187
|
+
btnEl.insertAdjacentHTML('beforeend', this.cfg.spinnerTpl);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Limit loading state to show only for the currently clicked button.
|
|
191
|
+
* Executed only if this.cfg.handleCurrentBtnOnly is set
|
|
192
|
+
*/
|
|
193
|
+
handleCurrentBtnOnly() {
|
|
194
|
+
if (!this.cfg.handleCurrentBtnOnly) {
|
|
195
|
+
return true; // return true for testing
|
|
196
|
+
}
|
|
197
|
+
// Click triggers @Input update
|
|
198
|
+
// We need to use timeout to wait for @Input to update
|
|
199
|
+
window.setTimeout(() => {
|
|
200
|
+
// return if something else than a promise is passed
|
|
201
|
+
if (!this.promise) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
this.initLoadingState(this.btnEl);
|
|
205
|
+
}, 0);
|
|
206
|
+
}
|
|
207
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PromiseBtnDirective, deps: [{ token: i0.ElementRef }, { token: userCfg }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
208
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: PromiseBtnDirective, isStandalone: false, selector: "[promiseBtn]", inputs: { isDisabledFromTheOutsideSetter: ["disabled", "isDisabledFromTheOutsideSetter"], promiseBtn: "promiseBtn" }, host: { listeners: { "click": "handleCurrentBtnOnly()" } }, ngImport: i0 }); }
|
|
209
|
+
}
|
|
210
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PromiseBtnDirective, decorators: [{
|
|
211
|
+
type: Directive,
|
|
212
|
+
args: [{
|
|
213
|
+
selector: '[promiseBtn]',
|
|
214
|
+
standalone: false
|
|
215
|
+
}]
|
|
216
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
|
|
217
|
+
type: Inject,
|
|
218
|
+
args: [userCfg]
|
|
219
|
+
}] }], propDecorators: { isDisabledFromTheOutsideSetter: [{
|
|
220
|
+
type: Input,
|
|
221
|
+
args: ['disabled']
|
|
222
|
+
}], promiseBtn: [{
|
|
223
|
+
type: Input
|
|
224
|
+
}], handleCurrentBtnOnly: [{
|
|
225
|
+
type: HostListener,
|
|
226
|
+
args: ['click']
|
|
227
|
+
}] } });
|
|
228
|
+
|
|
229
|
+
class NgxPromiseButtonModule {
|
|
230
|
+
// add forRoot to make it configurable
|
|
231
|
+
static forRoot(config) {
|
|
232
|
+
// NOTE: this is never allowed to contain any conditional logic
|
|
233
|
+
return {
|
|
234
|
+
ngModule: NgxPromiseButtonModule,
|
|
235
|
+
providers: [{ provide: userCfg, useValue: config }]
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxPromiseButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
239
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: NgxPromiseButtonModule, declarations: [PromiseBtnDirective], exports: [PromiseBtnDirective] }); }
|
|
240
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxPromiseButtonModule }); }
|
|
241
|
+
}
|
|
242
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxPromiseButtonModule, decorators: [{
|
|
243
|
+
type: NgModule,
|
|
244
|
+
args: [{
|
|
245
|
+
declarations: [
|
|
246
|
+
PromiseBtnDirective,
|
|
247
|
+
],
|
|
248
|
+
imports: [],
|
|
249
|
+
exports: [
|
|
250
|
+
PromiseBtnDirective,
|
|
251
|
+
],
|
|
252
|
+
providers: []
|
|
253
|
+
}]
|
|
254
|
+
}] });
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Generated bundle index. Do not edit.
|
|
258
|
+
*/
|
|
259
|
+
|
|
260
|
+
export { NgxPromiseButtonModule, PromiseBtnDirective };
|
|
261
|
+
//# sourceMappingURL=ngx-promise-buttons.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-promise-buttons.mjs","sources":["../../../projects/ngx-promise-buttons/src/default-promise-btn-config.ts","../../../projects/ngx-promise-buttons/src/user-cfg.ts","../../../projects/ngx-promise-buttons/src/promise-btn.directive.ts","../../../projects/ngx-promise-buttons/src/ngx-promise-buttons.module.ts","../../../projects/ngx-promise-buttons/src/ngx-promise-buttons.ts"],"sourcesContent":["import {PromiseBtnConfig} from './promise-btn-config';\r\n\r\nexport const DEFAULT_CFG: PromiseBtnConfig = {\r\n spinnerTpl: '<span class=\"btn-spinner\"></span>',\r\n disableBtn: true,\r\n btnLoadingClass: 'is-loading',\r\n handleCurrentBtnOnly: false,\r\n minDuration: null,\r\n};\r\n\r\n","import {InjectionToken} from '@angular/core';\r\n\r\nexport const userCfg = new InjectionToken('cfg');\r\n","import {AfterContentInit, Directive, ElementRef, HostListener, Inject, Input, OnDestroy} from '@angular/core';\r\nimport {Observable, Subscription} from 'rxjs';\r\nimport {DEFAULT_CFG} from './default-promise-btn-config';\r\nimport {PromiseBtnConfig} from './promise-btn-config';\r\nimport {userCfg} from './user-cfg';\r\n\r\n@Directive({\r\n selector: '[promiseBtn]',\r\n standalone: false\r\n})\r\n\r\nexport class PromiseBtnDirective implements OnDestroy, AfterContentInit {\r\n cfg: PromiseBtnConfig;\r\n // the timeout used for min duration display\r\n minDurationTimeout: number;\r\n // boolean to determine minDurationTimeout state\r\n isMinDurationTimeoutDone: boolean;\r\n // boolean to determine if promise was resolved\r\n isPromiseDone: boolean;\r\n // the promise button button element\r\n btnEl: HTMLElement;\r\n // the promise itself or a function expression\r\n // NOTE: we need the type any here as we might deal with custom promises like bluebird\r\n promise: any;\r\n\r\n // this is added to fix the overriding of the disabled state by the loading indicator button.\r\n @Input('disabled')\r\n set isDisabledFromTheOutsideSetter(v: boolean) {\r\n this.isDisabledFromTheOutside = v;\r\n if (v) {\r\n // disabled means always disabled\r\n this.btnEl.setAttribute('disabled', 'disabled');\r\n } else if (this.isPromiseDone || this.isPromiseDone === undefined) {\r\n this.btnEl.removeAttribute('disabled');\r\n }\r\n // else the button is loading, so do not change the disabled loading state.\r\n }\r\n\r\n isDisabledFromTheOutside: boolean;\r\n\r\n private _fakePromiseResolve: (value: void) => void;\r\n\r\n constructor(el: ElementRef,\r\n @Inject(userCfg) cfg: PromiseBtnConfig) {\r\n // provide configuration\r\n this.cfg = Object.assign({}, DEFAULT_CFG, cfg);\r\n\r\n // save element\r\n this.btnEl = el.nativeElement;\r\n }\r\n\r\n @Input()\r\n set promiseBtn(passedValue: any) {\r\n const isObservable: boolean = passedValue instanceof Observable;\r\n const isSubscription: boolean = passedValue instanceof Subscription;\r\n const isBoolean: boolean = typeof passedValue === 'boolean';\r\n const isPromise: boolean = passedValue instanceof Promise || (\r\n passedValue !== null &&\r\n typeof passedValue === 'object' &&\r\n typeof passedValue.then === 'function' &&\r\n typeof passedValue.catch === 'function'\r\n );\r\n\r\n if (isObservable) {\r\n throw new TypeError('promiseBtn must be an instance of Subscription, instance of Observable given');\r\n } else if (isSubscription) {\r\n const sub: Subscription = passedValue;\r\n if (!sub.closed) {\r\n this.promise = new Promise((resolve) => {\r\n sub.add(resolve);\r\n });\r\n }\r\n } else if (isPromise) {\r\n this.promise = passedValue;\r\n } else if (isBoolean) {\r\n this.promise = this.createPromiseFromBoolean(passedValue);\r\n }\r\n\r\n this.checkAndInitPromiseHandler(this.btnEl);\r\n }\r\n\r\n ngAfterContentInit() {\r\n this.prepareBtnEl(this.btnEl);\r\n // trigger changes once to handle initial promises\r\n this.checkAndInitPromiseHandler(this.btnEl);\r\n }\r\n\r\n ngOnDestroy() {\r\n // cleanup\r\n if (this.minDurationTimeout) {\r\n clearTimeout(this.minDurationTimeout);\r\n }\r\n }\r\n\r\n createPromiseFromBoolean(val: boolean): Promise<any> {\r\n if (val) {\r\n return new Promise((resolve) => {\r\n this._fakePromiseResolve = resolve;\r\n });\r\n } else {\r\n if (this._fakePromiseResolve) {\r\n this._fakePromiseResolve();\r\n }\r\n return this.promise;\r\n }\r\n }\r\n\r\n /**\r\n * Initializes all html and event handlers\r\n */\r\n prepareBtnEl(btnEl: HTMLElement) {\r\n // handle promises passed via promiseBtn attribute\r\n this.appendSpinnerTpl(btnEl);\r\n }\r\n\r\n /**\r\n * Checks if all required parameters are there and inits the promise handler\r\n */\r\n checkAndInitPromiseHandler(btnEl: HTMLElement) {\r\n // check if element and promise is set\r\n if (btnEl && this.promise) {\r\n this.initPromiseHandler(btnEl);\r\n }\r\n }\r\n\r\n /**\r\n * Helper FN to add class\r\n */\r\n addLoadingClass(el: any) {\r\n if (typeof this.cfg.btnLoadingClass === 'string') {\r\n el.classList.add(this.cfg.btnLoadingClass);\r\n }\r\n }\r\n\r\n /**\r\n * Helper FN to remove classes\r\n */\r\n removeLoadingClass(el: any) {\r\n if (typeof this.cfg.btnLoadingClass === 'string') {\r\n el.classList.remove(this.cfg.btnLoadingClass);\r\n }\r\n }\r\n\r\n /**\r\n * Handles everything to be triggered when the button is set\r\n * to loading state.\r\n */\r\n initLoadingState(btnEl: HTMLElement) {\r\n this.addLoadingClass(btnEl);\r\n this.disableBtn(btnEl);\r\n }\r\n\r\n /**\r\n * Handles everything to be triggered when loading is finished\r\n */\r\n cancelLoadingStateIfPromiseAndMinDurationDone(btnEl: HTMLElement) {\r\n if ((!this.cfg.minDuration || this.isMinDurationTimeoutDone) && this.isPromiseDone) {\r\n this.removeLoadingClass(btnEl);\r\n this.enableBtn(btnEl);\r\n }\r\n }\r\n\r\n disableBtn(btnEl: HTMLElement) {\r\n if (this.cfg.disableBtn) {\r\n btnEl.setAttribute('disabled', 'disabled');\r\n }\r\n }\r\n\r\n enableBtn(btnEl: HTMLElement) {\r\n if (this.cfg.disableBtn) {\r\n if (this.isDisabledFromTheOutside) {\r\n btnEl.setAttribute('disabled', 'disabled');\r\n } else {\r\n btnEl.removeAttribute('disabled');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Initializes a watcher for the promise. Also takes\r\n * this.cfg.minDuration into account if given.\r\n */\r\n\r\n initPromiseHandler(btnEl: HTMLElement) {\r\n const promise = this.promise;\r\n\r\n // watch promise to resolve or fail\r\n this.isMinDurationTimeoutDone = false;\r\n this.isPromiseDone = false;\r\n\r\n // create timeout if option is set\r\n if (this.cfg.minDuration) {\r\n this.minDurationTimeout = window.setTimeout(() => {\r\n this.isMinDurationTimeoutDone = true;\r\n this.cancelLoadingStateIfPromiseAndMinDurationDone(btnEl);\r\n }, this.cfg.minDuration);\r\n }\r\n\r\n const resolveLoadingState = () => {\r\n this.isPromiseDone = true;\r\n this.cancelLoadingStateIfPromiseAndMinDurationDone(btnEl);\r\n };\r\n\r\n if (!this.cfg.handleCurrentBtnOnly) {\r\n this.initLoadingState(btnEl);\r\n }\r\n // native Promise doesn't have finally\r\n if (promise.finally) {\r\n promise.finally(resolveLoadingState);\r\n } else {\r\n promise\r\n .then(resolveLoadingState)\r\n .catch(resolveLoadingState);\r\n }\r\n\r\n }\r\n\r\n\r\n /**\r\n * $compile and append the spinner template to the button.\r\n */\r\n appendSpinnerTpl(btnEl: HTMLElement) {\r\n // TODO add some kind of compilation later on\r\n btnEl.insertAdjacentHTML('beforeend', this.cfg.spinnerTpl as string);\r\n }\r\n\r\n /**\r\n * Limit loading state to show only for the currently clicked button.\r\n * Executed only if this.cfg.handleCurrentBtnOnly is set\r\n */\r\n @HostListener('click')\r\n handleCurrentBtnOnly() {\r\n if (!this.cfg.handleCurrentBtnOnly) {\r\n return true; // return true for testing\r\n }\r\n\r\n // Click triggers @Input update\r\n // We need to use timeout to wait for @Input to update\r\n window.setTimeout(() => {\r\n // return if something else than a promise is passed\r\n if (!this.promise) {\r\n return;\r\n }\r\n\r\n this.initLoadingState(this.btnEl);\r\n }, 0);\r\n }\r\n}\r\n","import {ModuleWithProviders, NgModule} from '@angular/core';\r\nimport {PromiseBtnDirective} from './promise-btn.directive';\r\nimport {PromiseBtnConfig} from './promise-btn-config';\r\nimport {userCfg} from './user-cfg';\r\n\r\n@NgModule({\r\n declarations: [\r\n PromiseBtnDirective,\r\n ],\r\n imports: [],\r\n exports: [\r\n PromiseBtnDirective,\r\n ],\r\n providers: []\r\n})\r\nexport class NgxPromiseButtonModule {\r\n // add forRoot to make it configurable\r\n static forRoot(config?: PromiseBtnConfig): ModuleWithProviders<NgxPromiseButtonModule> {\r\n // NOTE: this is never allowed to contain any conditional logic\r\n return {\r\n ngModule: NgxPromiseButtonModule,\r\n providers: [{provide: userCfg, useValue: config}]\r\n };\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ngx-promise-buttons",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Chilled loading buttons for angular",
|
|
5
|
+
"author": "meysamsahragard <contact@super-productivity.com> (http://super-productivity.com)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+ssh://git@github.com/meysamsahragard/ngx-promise-buttons.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"angular",
|
|
13
|
+
"javascript",
|
|
14
|
+
"typescript",
|
|
15
|
+
"button",
|
|
16
|
+
"promise",
|
|
17
|
+
"spinner"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"tslib": "^2.0.0"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"@angular/common": ">=9.0.4",
|
|
24
|
+
"@angular/core": ">=9.0.4"
|
|
25
|
+
},
|
|
26
|
+
"module": "fesm2022/ngx-promise-buttons.mjs",
|
|
27
|
+
"typings": "types/ngx-promise-buttons.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
"./package.json": {
|
|
30
|
+
"default": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./types/ngx-promise-buttons.d.ts",
|
|
34
|
+
"default": "./fesm2022/ngx-promise-buttons.mjs"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"sideEffects": false
|
|
38
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { OnDestroy, AfterContentInit, ElementRef, ModuleWithProviders } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
interface PromiseBtnConfig {
|
|
5
|
+
spinnerTpl?: string;
|
|
6
|
+
disableBtn?: boolean;
|
|
7
|
+
btnLoadingClass?: boolean | string;
|
|
8
|
+
handleCurrentBtnOnly?: boolean;
|
|
9
|
+
minDuration?: number | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare class PromiseBtnDirective implements OnDestroy, AfterContentInit {
|
|
13
|
+
cfg: PromiseBtnConfig;
|
|
14
|
+
minDurationTimeout: number;
|
|
15
|
+
isMinDurationTimeoutDone: boolean;
|
|
16
|
+
isPromiseDone: boolean;
|
|
17
|
+
btnEl: HTMLElement;
|
|
18
|
+
promise: any;
|
|
19
|
+
set isDisabledFromTheOutsideSetter(v: boolean);
|
|
20
|
+
isDisabledFromTheOutside: boolean;
|
|
21
|
+
private _fakePromiseResolve;
|
|
22
|
+
constructor(el: ElementRef, cfg: PromiseBtnConfig);
|
|
23
|
+
set promiseBtn(passedValue: any);
|
|
24
|
+
ngAfterContentInit(): void;
|
|
25
|
+
ngOnDestroy(): void;
|
|
26
|
+
createPromiseFromBoolean(val: boolean): Promise<any>;
|
|
27
|
+
/**
|
|
28
|
+
* Initializes all html and event handlers
|
|
29
|
+
*/
|
|
30
|
+
prepareBtnEl(btnEl: HTMLElement): void;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if all required parameters are there and inits the promise handler
|
|
33
|
+
*/
|
|
34
|
+
checkAndInitPromiseHandler(btnEl: HTMLElement): void;
|
|
35
|
+
/**
|
|
36
|
+
* Helper FN to add class
|
|
37
|
+
*/
|
|
38
|
+
addLoadingClass(el: any): void;
|
|
39
|
+
/**
|
|
40
|
+
* Helper FN to remove classes
|
|
41
|
+
*/
|
|
42
|
+
removeLoadingClass(el: any): void;
|
|
43
|
+
/**
|
|
44
|
+
* Handles everything to be triggered when the button is set
|
|
45
|
+
* to loading state.
|
|
46
|
+
*/
|
|
47
|
+
initLoadingState(btnEl: HTMLElement): void;
|
|
48
|
+
/**
|
|
49
|
+
* Handles everything to be triggered when loading is finished
|
|
50
|
+
*/
|
|
51
|
+
cancelLoadingStateIfPromiseAndMinDurationDone(btnEl: HTMLElement): void;
|
|
52
|
+
disableBtn(btnEl: HTMLElement): void;
|
|
53
|
+
enableBtn(btnEl: HTMLElement): void;
|
|
54
|
+
/**
|
|
55
|
+
* Initializes a watcher for the promise. Also takes
|
|
56
|
+
* this.cfg.minDuration into account if given.
|
|
57
|
+
*/
|
|
58
|
+
initPromiseHandler(btnEl: HTMLElement): void;
|
|
59
|
+
/**
|
|
60
|
+
* $compile and append the spinner template to the button.
|
|
61
|
+
*/
|
|
62
|
+
appendSpinnerTpl(btnEl: HTMLElement): void;
|
|
63
|
+
/**
|
|
64
|
+
* Limit loading state to show only for the currently clicked button.
|
|
65
|
+
* Executed only if this.cfg.handleCurrentBtnOnly is set
|
|
66
|
+
*/
|
|
67
|
+
handleCurrentBtnOnly(): boolean;
|
|
68
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PromiseBtnDirective, never>;
|
|
69
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<PromiseBtnDirective, "[promiseBtn]", never, { "isDisabledFromTheOutsideSetter": { "alias": "disabled"; "required": false; }; "promiseBtn": { "alias": "promiseBtn"; "required": false; }; }, {}, never, never, false, never>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
declare class NgxPromiseButtonModule {
|
|
73
|
+
static forRoot(config?: PromiseBtnConfig): ModuleWithProviders<NgxPromiseButtonModule>;
|
|
74
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NgxPromiseButtonModule, never>;
|
|
75
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<NgxPromiseButtonModule, [typeof PromiseBtnDirective], never, [typeof PromiseBtnDirective]>;
|
|
76
|
+
static ɵinj: i0.ɵɵInjectorDeclaration<NgxPromiseButtonModule>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { NgxPromiseButtonModule, PromiseBtnDirective };
|