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
30 changes: 30 additions & 0 deletions apps/demo/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,34 @@ <h2>Getting up and running...</h2>
</fab-command-bar>

<fab-calendar [strings]="strings" (onSelectDate)="onSelectDate($event)"></fab-calendar>

<fab-marquee-selection [isEnabled]="marqueeEnabled" [selection]="selection">
<fab-details-list [selection]="selection" [items]="detailItems" (onColumnHeaderClick)="onColumnHeaderClicked($event)">
<columns>
<fab-details-list-column key="column-1" [minWidth]="150" name="Column #1" fieldName="field1" [isResizable]="true">
</fab-details-list-column>
<fab-details-list-column key="column-2" [minWidth]="150" name="Column #2" fieldName="field2" [isResizable]="true">
</fab-details-list-column>
<fab-details-list-column key="column-3" [minWidth]="150" name="Custom Column" fieldName="field3" [isResizable]="true">
<render>
<ng-template let-index="index">
Custom content for index {{ index }}
</ng-template>
</render>
</fab-details-list-column>
</columns>
<groups>
<fab-group-item key="group-1" name="Group #1" [count]="3" [startIndex]="0">
<fab-group-item [level]="1" key="group-1-1" name="Nested Group #1.1" [count]="1" [startIndex]="0"></fab-group-item>
<fab-group-item [level]="1" key="group-1-2" name="Nested Group #1.2" [count]="2" [startIndex]="1"></fab-group-item>
</fab-group-item>
<fab-group-item key="group-2" name="Group #2" [count]="1" [startIndex]="3"></fab-group-item>
<fab-group-item key="group-3" name="Group #3" [count]="1" [startIndex]="4"></fab-group-item>
</groups>
</fab-details-list>
</fab-marquee-selection>
<div>{{ selection.count || 0 }} item(s) selected</div>
<fab-default-button (onClick)="marqueeEnabled = !marqueeEnabled">
Marquee {{ marqueeEnabled === false ? 'Disabled' : 'Enabled' }}
</fab-default-button>
</div>
20 changes: 18 additions & 2 deletions apps/demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectorRef, Component, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { ICalendarStrings, IContextualMenuProps } from 'office-ui-fabric-react';
import { ICalendarStrings, IContextualMenuProps, ISelection, Selection } from 'office-ui-fabric-react';

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

marqueeEnabled: boolean;
runDisabled: boolean;
selection: ISelection;

strings: ICalendarStrings = {
months: [
Expand Down Expand Up @@ -39,6 +41,14 @@ export class AppComponent {
weekNumberFormatString: 'Week number {0}',
};

detailItems = [
{ field1: 'f1content1', field2: 'f2content1' },
{ field1: 'f1content2', field2: 'f2content2' },
{ field1: 'f1content3', field2: 'f2content3' },
{ field1: 'f1content4' },
{ field2: 'f2content5' },
];

onNewClicked() {
console.log('New clicked');
}
Expand Down Expand Up @@ -68,7 +78,13 @@ export class AppComponent {
console.log($event);
}

constructor(private readonly cd: ChangeDetectorRef) {}
onColumnHeaderClicked(event: any) {
console.log('Column header clicked', event);
}

constructor(private readonly cd: ChangeDetectorRef) {
this.selection = new Selection();
}

customItemCount = 1;

Expand Down
6 changes: 6 additions & 0 deletions apps/demo/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ import {
FabComboBoxModule,
FabCommandBarModule,
FabDatePickerModule,
FabDetailsListModule,
FabDialogModule,
FabDividerModule,
FabFabricModule,
FabGroupModule,
FabGroupedListModule,
FabHoverCardModule,
FabIconModule,
FabImageModule,
FabLinkModule,
FabMarqueeSelectionModule,
FabMessageBarModule,
FabModalModule,
FabPanelModule,
Expand Down Expand Up @@ -67,6 +70,9 @@ import { CounterComponent } from './counter/counter.component';
FabSliderModule,
FabSearchBoxModule,
FabCalendarModule,
FabDetailsListModule,
FabGroupModule,
FabMarqueeSelectionModule
],
declarations: [AppComponent, CounterComponent],
bootstrap: [AppComponent],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ import {
export class FabCommandBarComponent extends ReactWrapperComponent<ICommandBarProps>
implements OnChanges<FabCommandBarComponent>, AfterContentInit, OnDestroy {
@ContentChild(CommandBarItemsDirective)
readonly itemsDirective: CommandBarItemsDirective;
readonly itemsDirective?: CommandBarItemsDirective;
@ContentChild(CommandBarFarItemsDirective)
readonly farItemsDirective: CommandBarFarItemsDirective;
readonly farItemsDirective?: CommandBarFarItemsDirective;
@ContentChild(CommandBarOverflowItemsDirective)
readonly overflowItemsDirective: CommandBarOverflowItemsDirective;
readonly overflowItemsDirective?: CommandBarOverflowItemsDirective;

@ViewChild('reactNode')
protected reactNodeRef: ElementRef;
Expand Down Expand Up @@ -188,7 +188,7 @@ export class FabCommandBarComponent extends ReactWrapperComponent<ICommandBarPro

// Subscribe for existing items changes
this._subscriptions.push(
directive.onItemChanged.subscribe(({ key, changes }: CommandBarItemChangedPayload) => {
directive.onChildItemChanged.subscribe(({ key, changes }: CommandBarItemChangedPayload) => {
setItems(items => items.map(item => (item.key === key ? mergeItemChanges(item, changes) : item)));
this.markForCheck();
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import {
AfterContentInit,
ContentChildren,
Directive,
EventEmitter,
OnDestroy,
Output,
QueryList,
} from '@angular/core';
import { Subscription } from 'rxjs';
import { ICommandBarItemOptions } from '../command-bar.component';
import { CommandBarItemChangedPayload, CommandBarItemDirective } from './command-bar-item.directives';
import { ContentChildren, Directive, QueryList } from '@angular/core';

export abstract class CommandBarItemsDirectiveBase implements AfterContentInit, OnDestroy {
private readonly _subscriptions: Subscription[] = [];
import { ChangeableItemsDirective } from '../../core/shared/changeable-items.directive';
import { ICommandBarItemOptions } from '../command-bar.component';
import { CommandBarItemDirective } from './command-bar-item.directives';

export abstract class CommandBarItemsDirectiveBase extends ChangeableItemsDirective<ICommandBarItemOptions> {
abstract readonly directiveItems: QueryList<CommandBarItemDirective>;

@Output()
readonly onItemChanged = new EventEmitter<CommandBarItemChangedPayload>();
@Output()
readonly onItemsChanged = new EventEmitter<QueryList<CommandBarItemDirective>>();

get items() {
return (
this.directiveItems &&
Expand All @@ -38,29 +24,6 @@ export abstract class CommandBarItemsDirectiveBase implements AfterContentInit,
}))
);
}

ngAfterContentInit() {
this._subscriptions.push(
...this.directiveItems.map(directiveItem =>
// Propagate the change to the parent CommandBarComponent
directiveItem.onItemChanged.subscribe(changes => this.onItemChangedHandler(changes))
)
);

this._subscriptions.push(
this.directiveItems.changes.subscribe((newValue: this['directiveItems']) => {
this.onItemsChanged.emit(newValue);
})
);
}

ngOnDestroy() {
this._subscriptions.forEach(subscription => subscription.unsubscribe());
}

private onItemChangedHandler(payload: CommandBarItemChangedPayload) {
this.onItemChanged.emit(payload);
}
}

@Directive({ selector: 'fab-command-bar > items' })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@ import {
QueryList,
} from '@angular/core';
import { IContextualMenuItem } from 'office-ui-fabric-react';
import { Subscription } from 'rxjs';
import { OnChanges, TypedChanges } from '../../../declarations/angular/typed-changes';
import { ItemChangedPayload } from '../../core/declarative/item-changed.payload';

export type ContextualMenuItemChangedPayload = ItemChangedPayload<IContextualMenuItem['key'], IContextualMenuItem>;
import { OnChanges } from '../../../declarations/angular/typed-changes';
import { ItemChangedPayload } from '../../core/declarative/item-changed.payload';
import { ChangeableItemsHelper, IChangeableItemsContainer } from '../../core/shared/changeable-helper';
import { ChangeableItemDirective } from '../../core/shared/changeable-item.directive';

@Directive({ selector: 'contextual-menu-item' })
export class ContextualMenuItemDirective
implements IContextualMenuItem, OnChanges<ContextualMenuItemDirective>, AfterContentInit, OnDestroy {
export class ContextualMenuItemDirective extends ChangeableItemDirective<IContextualMenuItem>
implements
AfterContentInit,
IChangeableItemsContainer<IContextualMenuItem>,
IContextualMenuItem,
OnChanges<ContextualMenuItemDirective>,
OnDestroy {
@ContentChildren(ContextualMenuItemDirective)
readonly menuItemsDirectives: QueryList<ContextualMenuItemDirective>;

@Input()
key: IContextualMenuItem['key'];
@Input()
componentRef?: IContextualMenuItem['componentRef'];
@Input()
Expand Down Expand Up @@ -94,53 +97,30 @@ export class ContextualMenuItemDirective
@Output()
readonly click = new EventEmitter<{ ev?: MouseEvent | KeyboardEvent; item?: IContextualMenuItem }>();

// Directive properties
@Output()
readonly onItemChanged = new EventEmitter<ContextualMenuItemChangedPayload>();

private readonly _subscriptions: Subscription[] = [];

ngOnChanges(changes: TypedChanges<this>) {
this.onItemChanged.emit({
key: this.key,
changes,
});
get onChildItemChanged(): EventEmitter<ItemChangedPayload<string, IContextualMenuItem>> {
return this.changeableItemsHelper && this.changeableItemsHelper.onChildItemChanged;
}
@Input()
get onItemsChanged(): EventEmitter<QueryList<ChangeableItemDirective<IContextualMenuItem>>> {
return this.changeableItemsHelper && this.changeableItemsHelper.onItemsChanged;
}

ngAfterContentInit() {
// @ContentChildren selects host component as well.
// Relevant GitHub issue: https://github.com/angular/angular/issues/10098
const nonSelfMenuItemsDirectives = this.menuItemsDirectives.filter(directive => directive !== this);
if (nonSelfMenuItemsDirectives.length === 0) {
return;
}

const items = nonSelfMenuItemsDirectives.map(directive => this._directiveToContextualMenuItem(directive));
if (!this.subMenuProps) {
this.subMenuProps = { items: items };
} else {
this.subMenuProps.items = items;
}
private changeableItemsHelper: ChangeableItemsHelper<IContextualMenuItem>;

this._subscriptions.push(
this.menuItemsDirectives.changes.subscribe((newValue: this['menuItemsDirectives']) => {
this.onItemChanged.emit({
key: this.key,
changes: {
subMenuProps: {
currentValue: {
...this.subMenuProps,
items: newValue.map(directive => this._directiveToContextualMenuItem(directive)),
},
},
},
});
})
);
ngAfterContentInit() {
this.changeableItemsHelper = new ChangeableItemsHelper(this.menuItemsDirectives, this, nonSelfDirective => {
const items = nonSelfDirective.map(directive => this._directiveToContextualMenuItem(directive as any));
if (!this.subMenuProps) {
this.subMenuProps = { items: items };
} else {
this.subMenuProps.items = items;
}
});
}

ngOnDestroy() {
this._subscriptions.forEach(subscription => subscription.unsubscribe());
this.changeableItemsHelper.destroy();
}

private _directiveToContextualMenuItem(directive: ContextualMenuItemDirective): IContextualMenuItem {
Expand Down
Loading