Created
June 30, 2016 12:17
-
-
Save bennadel/51d6a8e8b9fbadbe7a58121f428288e4 to your computer and use it in GitHub Desktop.
Using An Item Template With An HTML Dropdown Menu Component In Angular 2 RC 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Import the core angular services. | |
import { Component } from "@angular/core"; | |
// Import the application components and services. | |
import { HtmlDropdownComponent } from "./html-dropdown.component"; | |
interface Friend { | |
id: number; | |
name: string; | |
avatar: string; | |
} | |
@Component({ | |
selector: "my-app", | |
directives: [ HtmlDropdownComponent ], | |
// I our view, notice that we are providing a TemplateRef as a child element of the | |
// HtmlDropdownComponent. The dropdown component will query for this template and | |
// then use it to render both the option items as well as the root item. | |
template: | |
` | |
<p> | |
<strong>Best Friend</strong>: {{ bestFriend?.name || "None selected" }} | |
— | |
<a (click)="clearSelection()">Clear selection</a> | |
</p> | |
<html-dropdown | |
[items]="friends" | |
[(value)]="bestFriend" | |
placeholder="Select Friend"> | |
<template let-friend="item"> | |
<img [src]="( './img/' + friend.avatar )" /> | |
<span class="name"> | |
{{ friend.name }} | |
</span> | |
</template> | |
</html-dropdown> | |
` | |
}) | |
export class AppComponent { | |
// I hold the friend that is selected as the best friend. | |
public bestFriend: Friend; | |
// I hold the collection of friends. | |
public friends: Friend[]; | |
// I initialize the component. | |
constructor() { | |
this.bestFriend = null; | |
this.friends = [ | |
{ | |
id: 1, | |
name: "Joanna", | |
avatar: "joanna-avatar.jpg" | |
}, | |
{ | |
id: 2, | |
name: "Kim", | |
avatar: "kim-avatar.jpg" | |
}, | |
{ | |
id: 3, | |
name: "Sarah", | |
avatar: "sarah-avatar.jpg" | |
}, | |
{ | |
id: 4, | |
name: "Tricia", | |
avatar: "tricia-avatar.jpg" | |
} | |
]; | |
} | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
// I clear the best-friend selection. | |
public clearSelection() : void { | |
this.bestFriend = null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Import the core angular services. | |
import { Component } from "@angular/core"; | |
import { ContentChild } from "@angular/core"; | |
import { EventEmitter } from "@angular/core"; | |
import { TemplateRef } from "@angular/core"; | |
@Component({ | |
selector: "html-dropdown", | |
inputs: [ "items", "value", "placeholder" ], | |
outputs: [ "valueChange" ], | |
// Query for the template being provided by the calling context. | |
queries: { | |
itemTemplate: new ContentChild( TemplateRef ) | |
}, | |
host: { | |
"[class.is-open]": "isShowingItems" | |
}, | |
template: | |
` | |
<div (click)="toggleItems()" class="dropdown-root" [ngSwitch]="!! value"> | |
<div *ngSwitchCase="true" class="dropdown-item-content"> | |
<template | |
[ngTemplateOutlet]="itemTemplate" | |
[ngOutletContext]="{ item: value, index: -1 }"> | |
</template> | |
</div> | |
<div *ngSwitchCase="false" class="placeholder"> | |
{{ placeholder || "Nothing Selected" }} | |
</div> | |
</div> | |
<ul *ngIf="isShowingItems" class="dropdown-items"> | |
<li | |
*ngFor="let item of items ; let index = index ;" | |
(click)="selectItem( item )" | |
class="dropdown-item"> | |
<div class="dropdown-item-content"> | |
<template | |
[ngTemplateOutlet]="itemTemplate" | |
[ngOutletContext]="{ item: item, index: index }"> | |
</template> | |
</div> | |
</li> | |
</ul> | |
` | |
}) | |
export class HtmlDropdownComponent { | |
// I determine if the dropdown items are being shown. | |
public isShowingItems: boolean; | |
// INPUT: I am the collection of items used to render the dropdown items. | |
public items: any[]; | |
// INPUT: I am the text to show when no item is selected. | |
public placeholder: string; | |
// INPUT: I am the currently selected value. | |
public value: any; | |
// OUTPUT: I am the output event stream that emits the item selected by the user. | |
public valueChange: EventEmitter<any>; | |
// I initialize the component. | |
constructor() { | |
this.isShowingItems = false; | |
this.valueChange = new EventEmitter(); | |
} | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
// I hide the dropdown items. | |
public hideItems() : void { | |
this.isShowingItems = false; | |
} | |
// I select the given item. | |
// -- | |
// NOTE: Since this is a one-way data flow, the selection is being emitted rather | |
// than applied directly to the value. | |
public selectItem( item: any ) : void { | |
this.hideItems(); | |
this.valueChange.emit( item ); | |
} | |
// I show the dropdown items. | |
public showItems() : void { | |
this.isShowingItems = true; | |
} | |
// I show or hide the dropdown items depending on their current visibility. | |
public toggleItems() : void { | |
this.isShowingItems | |
? this.hideItems() | |
: this.showItems() | |
; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment