Skip to content

Commit ee489ea

Browse files
authored
Merge pull request #4 from kreuzerk/feature/supportAsyncPipe
Feature/support async pipe
2 parents daa80b3 + d8aa7d4 commit ee489ea

File tree

13 files changed

+240
-36
lines changed

13 files changed

+240
-36
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Import the ```NgsgModule``` in your ```AppModule```.
2929
```
3030

3131
## Apply the directive
32-
Loop over your elements with *ngFor. 🛎️ the items needs to be an array.
32+
Loop over your elements with *ngFor. 🛎️ the items needs to be an array. Alternate you can also use the async pipe to pass in your items.
3333

3434
![Grid demo](https://raw.githubusercontent.com/kreuzerk/ng-sortgrid/master/projects/ng-sortgrid-demo/src/assets/gs1.png)
3535

projects/ng-sortgrid-demo/src/app/app.component.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<div class="container">
55
<h1>1. Getting started</h1>
6-
<ngsg-demo-step title="Loop over your elements with *ngFor. 🛎️ the items needs to be an array." image="gs1.png"></ngsg-demo-step>
6+
<ngsg-demo-step title="Loop over your elements with *ngFor. 🛎️ the items needs to be an array. Alternate you can also use the async pipe - see below" image="gs1.png"></ngsg-demo-step>
77
<ngsg-demo-step title="Apply the ngSortgridItem directive" image="gs2.png"></ngsg-demo-step>
88
<ngsg-demo-memory></ngsg-demo-memory>
99

@@ -22,6 +22,11 @@ <h1>3. Group sortgrids</h1>
2222
one group in another group.</p>
2323
<ngsg-demo-step title="Pass in a unique name to the ngSortGridGroup input" image="gs5.png"></ngsg-demo-step>
2424
<ngsg-demo-groups-memory></ngsg-demo-groups-memory>
25+
26+
<hr class="chaptor-separator"/>
27+
<h1>4. Use the async pipe</h1>
28+
<ngsg-demo-step title="Use the async pipe to loop over the items and to pass in the ngSortGridItems" image="gs6.png"></ngsg-demo-step>
29+
<ngsg-demo-async></ngsg-demo-async>
2530
</div>
2631

2732
<footer class="py-5 bg-dark">

projects/ng-sortgrid-demo/src/app/app.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {StepComponent} from './examples/step/step.component';
1010
import {ReactOnChangesMemoryComponent} from './examples/react-on-changes/react-on-changes-memory.component';
1111
import {GroupsMemoryComponent} from './examples/groups/groups-memory.component';
1212
import {CardComponent} from './examples/card/card.component';
13+
import {AsyncPipeMemoryComponent} from './examples/async-pipe/async-pipe-memory.component';
1314

1415
@NgModule({
1516
declarations: [
@@ -20,7 +21,8 @@ import {CardComponent} from './examples/card/card.component';
2021
StepComponent,
2122
ReactOnChangesMemoryComponent,
2223
GroupsMemoryComponent,
23-
CardComponent
24+
CardComponent,
25+
AsyncPipeMemoryComponent
2426
],
2527
imports: [BrowserModule, NgsgModule],
2628
providers: [],
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.spinner {
2+
width: 40px;
3+
height: 40px;
4+
5+
position: relative;
6+
margin: 100px auto;
7+
}
8+
9+
.double-bounce1, .double-bounce2 {
10+
width: 100%;
11+
height: 100%;
12+
border-radius: 50%;
13+
background-color: #333;
14+
opacity: 0.6;
15+
position: absolute;
16+
top: 0;
17+
left: 0;
18+
19+
-webkit-animation: sk-bounce 2.0s infinite ease-in-out;
20+
animation: sk-bounce 2.0s infinite ease-in-out;
21+
}
22+
23+
.double-bounce2 {
24+
-webkit-animation-delay: -1.0s;
25+
animation-delay: -1.0s;
26+
}
27+
28+
@-webkit-keyframes sk-bounce {
29+
0%, 100% { -webkit-transform: scale(0.0) }
30+
50% { -webkit-transform: scale(1.0) }
31+
}
32+
33+
@keyframes sk-bounce {
34+
0%, 100% {
35+
transform: scale(0.0);
36+
-webkit-transform: scale(0.0);
37+
} 50% {
38+
transform: scale(1.0);
39+
-webkit-transform: scale(1.0);
40+
}
41+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<h5 style="margin-bottom: 20px">4. Load items and use them with the async pipe</h5>
2+
<button style="margin-bottom: 20px" class="btn btn-primary" (click)="loadItems()">Load items</button>
3+
<div class="card border-primary mb-3">
4+
<div class="card-body">
5+
<h1 class="card-title">Sort order</h1>
6+
<h2 class="card-text">{{ sortOrder }}</h2>
7+
</div>
8+
</div>
9+
<div class="example-container">
10+
<div *ngIf="loading" class="spinner">
11+
<div class="double-bounce1"></div>
12+
<div class="double-bounce2"></div>
13+
</div>
14+
<ngsg-card *ngFor="let item of item$ | async"
15+
ngSortgridItem
16+
ngSortGridGroup="async-items"
17+
[ngSortGridItems]="item$ | async"
18+
[item]="item"
19+
(sorted)="applyOrder($event)"
20+
class="example-box">
21+
</ngsg-card>
22+
</div>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {Component} from '@angular/core';
2+
import {Observable, of} from 'rxjs';
3+
import {delay, tap} from 'rxjs/operators';
4+
5+
@Component({
6+
selector: 'ngsg-demo-async',
7+
templateUrl: './async-pipe-memory.component.html',
8+
styleUrls: ['./async-pipe-memory.component.css', '../memory-demo.css']
9+
})
10+
export class AsyncPipeMemoryComponent {
11+
12+
item$: Observable<number[]>;
13+
loading = false;
14+
public sortOrder: number[];
15+
16+
public loadItems(): void {
17+
this.loading = true;
18+
this.item$ = of([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).pipe(
19+
delay(1500),
20+
tap(() => this.loading = false)
21+
);
22+
}
23+
24+
public applyOrder(newOrder: number[]): void {
25+
this.sortOrder = newOrder;
26+
}
27+
28+
}

projects/ng-sortgrid-demo/src/app/examples/getting-started/getting-started-memory.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ <h5 style="margin-bottom: 20px">3. Drag the items around - hold CMD or Control a
33
<div class="example-container">
44
<ngsg-card *ngFor="let item of items"
55
ngSortgridItem
6+
ngSortGridGroup="getting-started"
67
[ngSortGridItems]="items"
78
[item]="item"
89
class="example-box">

projects/ng-sortgrid-demo/src/app/examples/react-on-changes/react-on-changes-memory.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ <h2 class="card-text">{{ sortOrder }}</h2>
77
<div class="example-container">
88
<ngsg-card *ngFor="let item of items"
99
ngSortgridItem
10+
ngSortGridGroup="react-on-changes"
1011
[item]="item"
1112
[ngSortGridItems]="items"
1213
(sorted)="applyOrder($event)"
81.8 KB
Loading

projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,34 @@ import createSpy = jasmine.createSpy;
1010
import {NgsgElementsHelper} from './ngsg-elements.helper';
1111

1212
describe('NgsgItemDirective', () => {
13-
1413
let sut: NgsgItemDirective;
1514

1615
const elementRef = {nativeElement: {}};
1716
const ngsgSortService = createSpyObj<NgsgSortService>('ngsgSortService', ['initSort', 'sort', 'endSort']);
18-
const ngsgSelectionService = createSpyObj<NgsgSelectionService>('ngsgSelectionService',
19-
['selectElementIfNoSelection', 'updateSelectedDragItem']);
17+
const ngsgSelectionService = createSpyObj<NgsgSelectionService>('ngsgSelectionService', [
18+
'selectElementIfNoSelection',
19+
'updateSelectedDragItem'
20+
]);
2021
const ngsgReflectService = createSpyObj<NgsgReflectService>('ngsgReflectService', ['reflectChanges']);
21-
const ngsgStore = createSpyObj<NgsgStoreService>('ngsgStore',
22-
['initState', 'hasSelectedItems', 'resetSelectedItems']);
22+
const ngsgStore = createSpyObj<NgsgStoreService>('ngsgStore', [
23+
'initState',
24+
'hasSelectedItems',
25+
'resetSelectedItems',
26+
'hasGroup',
27+
'hasItems',
28+
'setItems'
29+
]);
2330
const ngsgEventService = new NgsgEventsService();
2431

2532
beforeEach(() => {
26-
sut = new NgsgItemDirective(elementRef, ngsgSortService, ngsgSelectionService,
27-
ngsgReflectService, ngsgStore, ngsgEventService);
28-
});
29-
30-
it('should log a warning if we do not pass in sort grid items', () => {
31-
const consoleWarnSpy = spyOn(global.console, 'warn');
32-
sut.ngOnInit();
33-
expect(consoleWarnSpy).toHaveBeenCalledWith(
34-
`Ng-sortgrid: No items provided - please use [sortGridItems] to pass in an array of items -
35-
otherwhise the ordered items will not be emitted in the (sorted) event`);
36-
});
37-
38-
it('should init the store with the sortGridGroup, the ngSortGridItems and the classes', () => {
39-
const sortGridGroup = 'sortgridgroup';
40-
const sortGridItems = ['item one', 'item two', 'item three'] as any;
41-
sut.ngSortGridItems = sortGridItems;
42-
sut.ngSortGridGroup = sortGridGroup;
43-
44-
sut.ngOnInit();
45-
expect(ngsgStore.initState).toHaveBeenCalledWith(sortGridGroup, sortGridItems, {});
33+
sut = new NgsgItemDirective(
34+
elementRef,
35+
ngsgSortService,
36+
ngsgSelectionService,
37+
ngsgReflectService,
38+
ngsgStore,
39+
ngsgEventService
40+
);
4641
});
4742

4843
it('should set the draggable attribute on the elment', () => {
@@ -133,6 +128,7 @@ describe('NgsgItemDirective', () => {
133128

134129
it('should sort if the group contains selectedItems', () => {
135130
ngsgStore.hasSelectedItems.and.returnValue(true);
131+
ngsgStore.hasItems.and.returnValue(true);
136132
sut.drop({target: {matches: () => true}});
137133
expect(ngsgSortService.endSort).toHaveBeenCalled();
138134
});
@@ -169,6 +165,7 @@ describe('NgsgItemDirective', () => {
169165
const reflectedChanges = ['item two', 'item one', 'item three'];
170166

171167
ngsgStore.hasSelectedItems.and.returnValue(true);
168+
ngsgStore.hasItems.and.returnValue(true);
172169
ngsgReflectService.reflectChanges.and.returnValue(reflectedChanges);
173170
sut.ngSortGridGroup = group;
174171

@@ -212,4 +209,58 @@ describe('NgsgItemDirective', () => {
212209
expect(ngsgSelectionService.updateSelectedDragItem).toHaveBeenCalledWith(group, host, true);
213210
});
214211

212+
it(`should init the state with empty items if group has yet not been
213+
initialized and the currentValue is null`, () => {
214+
const group = 'test-group';
215+
const changes = {
216+
ngSortGridItems: {
217+
currentValue: null
218+
}
219+
} as any;
220+
sut.ngSortGridGroup = group;
221+
ngsgStore.hasGroup.and.returnValue(false);
222+
223+
sut.ngOnChanges(changes);
224+
expect(ngsgStore.initState).toHaveBeenCalledWith(group, []);
225+
});
226+
227+
it('should init the state with items from the currentValue if group has yet not been initialized', () => {
228+
const group = 'test-group';
229+
const changes = {
230+
ngSortGridItems: {
231+
currentValue: null
232+
}
233+
} as any;
234+
sut.ngSortGridGroup = group;
235+
ngsgStore.hasGroup.and.returnValue(false);
236+
237+
sut.ngOnChanges(changes);
238+
expect(ngsgStore.initState).toHaveBeenCalledWith(group, []);
239+
});
240+
241+
it('should set the items if the group has allready been initialized', () => {
242+
const group = 'test-group';
243+
const items = ['Item one', 'item two'];
244+
const changes = {
245+
ngSortGridItems: {
246+
currentValue: items
247+
}
248+
} as any;
249+
sut.ngSortGridGroup = group;
250+
ngsgStore.hasGroup.and.returnValue(true);
251+
252+
sut.ngOnChanges(changes);
253+
expect(ngsgStore.setItems).toHaveBeenCalledWith(group, items);
254+
});
255+
256+
it('should log a warning message if you drop and you did not provide any items', () => {
257+
const expectedWarniningMessage =
258+
`Ng-sortgrid: No items provided - please use [sortGridItems] to pass in an array of items -
259+
otherwhise the ordered items can not be emitted in the (sorted) event`;
260+
const consoleWarnSpy = spyOn(console, 'warn');
261+
ngsgStore.hasItems.and.returnValue(false);
262+
263+
sut.drop(event);
264+
expect(consoleWarnSpy).toHaveBeenCalledWith(expectedWarniningMessage);
265+
});
215266
});

0 commit comments

Comments
 (0)