Skip to content

Commit

Permalink
feat(dropdown): added inline style of adding dropdown, enabled by def…
Browse files Browse the repository at this point in the history
…ault

if container is set, than placement and dynamic place of dropdown menu will work

fixes #1860, fixes #1862
  • Loading branch information
valorkin committed Apr 5, 2017
1 parent 838821a commit f4334a8
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 12 deletions.
2 changes: 1 addition & 1 deletion demo/src/app/components/+dropdown/demos/config/config.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div dropdown>
<div class="btn-group" dropdown>
<button dropdownToggle type="button" class="btn btn-primary dropdown-toggle">
Button dropdown <span class="caret"></span>
</button>
Expand Down
6 changes: 6 additions & 0 deletions src/component-loader/bs-component-ref.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TemplateRef, ViewContainerRef } from '@angular/core';

export class BsComponentRef<T> {
templateRef: TemplateRef<T>;
viewContainer: ViewContainerRef;
}
12 changes: 8 additions & 4 deletions src/dropdown/bs-dropdown-menu.directive.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Directive, TemplateRef } from '@angular/core';
import { Directive, TemplateRef, ViewContainerRef } from '@angular/core';
import { BsDropdownState } from './bs-dropdown.state';

@Directive({
selector: '[bsDropdownMenu],[dropdownMenu]',
exportAs: 'bs-dropdown-menu'
})
export class BsDropdownMenuDirective {
constructor(private _state: BsDropdownState,
private _templateRef: TemplateRef<any>) {
_state.resolveDropdownMenu(_templateRef);
constructor(_state: BsDropdownState,
_viewContainer: ViewContainerRef,
_templateRef: TemplateRef<any>) {
_state.resolveDropdownMenu({
templateRef: _templateRef,
viewContainer: _viewContainer
});
}
}
40 changes: 36 additions & 4 deletions src/dropdown/bs-dropdown.directive.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output,
Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Input, OnDestroy, OnInit, Output,
Renderer, ViewContainerRef
} from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
Expand All @@ -9,6 +9,8 @@ import { ComponentLoader, ComponentLoaderFactory } from '../component-loader';
import { BsDropdownConfig } from './bs-dropdown.config';
import { BsDropdownContainerComponent } from './bs-dropdown-container.component';
import { BsDropdownState } from './bs-dropdown.state';
import { BsComponentRef } from '../component-loader/bs-component-ref.class';
import { BsDropdownMenuDirective } from './';

@Directive({
selector: '[bsDropdown],[dropdown]',
Expand Down Expand Up @@ -67,7 +69,11 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
/**
* Returns whether or not the popover is currently being shown
*/
@HostBinding('class.open')
@Input() get isOpen(): boolean {
if (this._showInline) {
return this._isInlineOpen;
}
return this._dropdown.isShown;
}

Expand All @@ -88,6 +94,11 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
*/
@Output() onHidden: EventEmitter<any>;

// todo: move to component loader
private _isInlineOpen = false;
private _showInline: boolean;
private _inlinedMenu: EmbeddedViewRef<BsDropdownMenuDirective>;

private _isDisabled: boolean;
private _dropdown: ComponentLoader<BsDropdownContainerComponent>;
private _subscriptions: Subscription[] = [];
Expand All @@ -108,6 +119,8 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
}

ngOnInit(): void {
this._showInline = !this.container;

// attach DOM listeners
this._dropdown.listen({
triggers: this.triggers,
Expand All @@ -126,14 +139,28 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
.isDisabledChange
.filter((value: boolean) => value === true)
.subscribe((value: boolean) => this.hide()));

// attach dropdown menu inside of dropdown
if (this._showInline) {
this._state.dropdownMenu
.then((dropdownMenu:BsComponentRef<BsDropdownMenuDirective>) => {
this._inlinedMenu = dropdownMenu.viewContainer.createEmbeddedView(dropdownMenu.templateRef);
});
}
}

/**
* Opens an element’s popover. This is considered a “manual” triggering of
* the popover.
*/
show(): void {
if (this._dropdown.isShown || this.isDisabled) {
if (this.isOpen || this.isDisabled) {
return;
}

if (this._showInline) {
this._isInlineOpen = true;
this._state.isOpenChange.emit(true);
return;
}

Expand All @@ -152,7 +179,7 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
.to(this.container)
.position({attachment: _placement})
.show({
content: dropdownMenu,
content: dropdownMenu.templateRef,
placement: _placement
});

Expand All @@ -169,7 +196,12 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
return;
}

this._dropdown.hide();
if (this._showInline) {
this._isInlineOpen = false;
} else {
this._dropdown.hide();
}

this._state.isOpenChange.emit(false);
}

Expand Down
7 changes: 4 additions & 3 deletions src/dropdown/bs-dropdown.state.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EventEmitter, Injectable, TemplateRef } from '@angular/core';
import { EventEmitter, Injectable } from '@angular/core';
import { BsComponentRef } from '../component-loader/bs-component-ref.class';

@Injectable()
export class BsDropdownState {
Expand All @@ -11,8 +12,8 @@ export class BsDropdownState {
/**
* Content to be displayed as popover.
*/
dropdownMenu: Promise<TemplateRef<any>>;
resolveDropdownMenu: Function;
dropdownMenu: Promise<BsComponentRef<any>>;
resolveDropdownMenu: (componentRef: BsComponentRef<any>) => void;

constructor() {
this.dropdownMenu = new Promise((resolve) => {
Expand Down

0 comments on commit f4334a8

Please sign in to comment.