Skip to content

Commit 0eff80c

Browse files
committed
Added DetailsList, GroupItem, and MarqueeSelection components; Created changeable-item/changeable-items directives
1 parent 2b7b9a9 commit 0eff80c

21 files changed

+977
-3
lines changed

apps/demo/src/app/app.component.html

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,34 @@ <h2>Getting up and running...</h2>
6464
</fab-command-bar>
6565

6666
<fab-calendar [strings]="strings" (onSelectDate)="onSelectDate($event)"></fab-calendar>
67-
</div>
67+
68+
<fab-marquee-selection [isEnabled]="marqueeEnabled" [selection]="selection">
69+
<fab-details-list [selection]="selection" [items]="detailItems" (onColumnHeaderClick)="onColumnHeaderClicked($event)">
70+
<columns>
71+
<fab-details-list-column key="column-1" [minWidth]="150" name="Column #1" fieldName="field1" [isResizable]="true">
72+
</fab-details-list-column>
73+
<fab-details-list-column key="column-2" [minWidth]="150" name="Column #2" fieldName="field2" [isResizable]="true">
74+
</fab-details-list-column>
75+
<fab-details-list-column key="column-3" [minWidth]="150" name="Custom Column" fieldName="field3" [isResizable]="true">
76+
<render>
77+
<ng-template let-index="index">
78+
Custom content for index {{ index }}
79+
</ng-template>
80+
</render>
81+
</fab-details-list-column>
82+
</columns>
83+
<groups>
84+
<fab-group-item key="group-1" name="Group #1" [count]="3" [startIndex]="0">
85+
<fab-group-item [level]="1" key="group-1-1" name="Nested Group #1.1" [count]="1" [startIndex]="0"></fab-group-item>
86+
<fab-group-item [level]="1" key="group-1-2" name="Nested Group #1.2" [count]="2" [startIndex]="1"></fab-group-item>
87+
</fab-group-item>
88+
<fab-group-item key="group-2" name="Group #2" [count]="1" [startIndex]="3"></fab-group-item>
89+
<fab-group-item key="group-3" name="Group #3" [count]="1" [startIndex]="4"></fab-group-item>
90+
</groups>
91+
</fab-details-list>
92+
</fab-marquee-selection>
93+
<div>{{ selection.count || 0 }} item(s) selected</div>
94+
<fab-default-button (click)="marqueeEnabled = !marqueeEnabled">
95+
Marque {{ marqueeEnabled === false ? 'Disabled' : 'Enabled' }}
96+
</fab-default-button>
97+
</div>

apps/demo/src/app/app.component.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ChangeDetectorRef, Component, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
2-
import { ICalendarStrings, IContextualMenuProps } from 'office-ui-fabric-react';
2+
import { ICalendarStrings, IContextualMenuProps, ISelection, Selection } from 'office-ui-fabric-react';
33

44
@Component({
55
selector: 'app-root',
@@ -11,7 +11,9 @@ export class AppComponent {
1111
@ViewChild('customRange')
1212
customRangeTemplate: TemplateRef<{ item: any; dismissMenu: (ev?: any, dismissAll?: boolean) => void }>;
1313

14+
marqueeEnabled: boolean;
1415
runDisabled: boolean;
16+
selection: ISelection;
1517

1618
strings: ICalendarStrings = {
1719
months: [
@@ -39,6 +41,14 @@ export class AppComponent {
3941
weekNumberFormatString: 'Week number {0}',
4042
};
4143

44+
detailItems = [
45+
{ 'field1': 'f1content1', 'field2': 'f2content1' },
46+
{ 'field1': 'f1content2', 'field2': 'f2content2' },
47+
{ 'field1': 'f1content3', 'field2': 'f2content3' },
48+
{ 'field1': 'f1content4' },
49+
{ 'field2': 'f2content5' }
50+
]
51+
4252
onNewClicked() {
4353
console.log('New clicked');
4454
}
@@ -68,7 +78,13 @@ export class AppComponent {
6878
console.log($event);
6979
}
7080

71-
constructor(private readonly cd: ChangeDetectorRef) {}
81+
onColumnHeaderClicked(event: any) {
82+
console.log('Column header clicked', event);
83+
}
84+
85+
constructor(private readonly cd: ChangeDetectorRef) {
86+
this.selection = new Selection();
87+
}
7288

7389
customItemCount = 1;
7490

apps/demo/src/app/app.module.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ import {
99
FabComboBoxModule,
1010
FabCommandBarModule,
1111
FabDatePickerModule,
12+
FabDetailsListModule,
1213
FabDialogModule,
1314
FabDividerModule,
1415
FabFabricModule,
16+
FabGroupModule,
1517
FabGroupedListModule,
1618
FabHoverCardModule,
1719
FabIconModule,
1820
FabImageModule,
1921
FabLinkModule,
22+
FabMarqueeSelectionModule,
2023
FabMessageBarModule,
2124
FabModalModule,
2225
FabPanelModule,
@@ -67,6 +70,9 @@ import { CounterComponent } from './counter/counter.component';
6770
FabSliderModule,
6871
FabSearchBoxModule,
6972
FabCalendarModule,
73+
FabDetailsListModule,
74+
FabGroupModule,
75+
FabMarqueeSelectionModule
7076
],
7177
declarations: [AppComponent, CounterComponent],
7278
bootstrap: [AppComponent],
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
import { EventEmitter, Input, Output } from '@angular/core';
5+
6+
import { OnChanges, TypedChanges } from '../../../declarations/angular/typed-changes';
7+
import { ItemChangedPayload } from '../../core/declarative/item-changed.payload';
8+
9+
/**
10+
* Parent class for wrapper directive for single item with OnChanges
11+
*/
12+
export abstract class ChangeableItemDirective<TItem>
13+
implements OnChanges<ChangeableItemDirective<TItem>> {
14+
15+
@Input()
16+
key: string;
17+
18+
@Output()
19+
readonly onItemChanged = new EventEmitter<ItemChangedPayload<string, TItem>>();
20+
21+
ngOnChanges(changes: TypedChanges<TItem>) {
22+
this.onItemChanged.emit({ key: this.key, changes });
23+
}
24+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
import { AfterContentInit, ContentChildren, EventEmitter, OnDestroy, Output, QueryList }
5+
from '@angular/core';
6+
import { Subscription } from 'rxjs';
7+
8+
import { ItemChangedPayload } from '../../core/declarative/item-changed.payload';
9+
import { ChangeableItemDirective } from './changeable-item.directive';
10+
11+
/**
12+
* Parent class for wrapper directive for multiple ChangeableItemDirectives
13+
*/
14+
export abstract class ChangeableItemsDirective<TItem> implements AfterContentInit, OnDestroy {
15+
16+
@ContentChildren(ChangeableItemDirective)
17+
readonly directiveItems: QueryList<ChangeableItemDirective<TItem>>;
18+
19+
@Output()
20+
readonly onItemChanged = new EventEmitter<ItemChangedPayload<string, TItem>>();
21+
@Output()
22+
readonly onItemsChanged = new EventEmitter<QueryList<ChangeableItemDirective<TItem>>>();
23+
24+
private readonly _subscriptions: Subscription[] = [];
25+
26+
abstract get items(): TItem[];
27+
28+
ngAfterContentInit() {
29+
this._subscriptions.push(
30+
...this.directiveItems.map((directiveItem: ChangeableItemDirective<TItem>) =>
31+
directiveItem.onItemChanged.subscribe((changes: ItemChangedPayload<string, TItem>) =>
32+
this.onItemChanged.emit(changes)
33+
)
34+
)
35+
);
36+
37+
this._subscriptions.push(
38+
this.directiveItems.changes.subscribe((newValue: this['directiveItems']) => {
39+
this.onItemsChanged.emit(newValue);
40+
})
41+
);
42+
}
43+
44+
ngOnDestroy() {
45+
this._subscriptions.forEach((sub: Subscription) => sub.unsubscribe());
46+
}
47+
}

0 commit comments

Comments
 (0)