Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created June 30, 2016 12:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bennadel/51d6a8e8b9fbadbe7a58121f428288e4 to your computer and use it in GitHub Desktop.
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
// 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" }}
&mdash;
<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;
}
}
// 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