JSFiddle - React, Tailwind, and code Playground
by bilbobaggins
HTML
<div ng-controller="ContactChipDemoCtrl as ctrl" layout="column" ng-cloak="" class="chipsdemoContactChips" ng-app="MyApp">
<md-content class="md-padding autocomplete" layout="column">
<md-contact-chips ng-model="ctrl.contacts" md-contacts="ctrl.querySearch($query)" md-contact-name="name" md-contact-image="image" md-contact-email="email" md-require-match="true" md-highlight-flags="i" filter-selected="ctrl.filterSelected" placeholder="To">
</md-contact-chips>
<md-list class="fixedRows">
<md-subheader class="md-no-sticky">Contacts</md-subheader>
<md-list-item class="md-2-line contact-item" ng-repeat="(index, contact) in ctrl.allContacts" ng-if="ctrl.contacts.indexOf(contact) < 0">
<img ng-src="{{contact.image}}" class="md-avatar" alt="{{contact.name}}">
<div class="md-list-item-text compact">
<h3>{{contact.name}}</h3>
<p>{{contact.email}}</p>
</div>
</md-list-item>
<md-list-item class="md-2-line contact-item selected" ng-repeat="(index, contact) in ctrl.contacts">
<img ng-src="{{contact.image}}" class="md-avatar" alt="{{contact.name}}">
<div class="md-list-item-text compact">
<h3>{{contact.name}}</h3>
<p>{{contact.email}}</p>
</div>
</md-list-item>
</md-list>
<br>
<h2 class="md-title">Searching asynchronously.</h2>
<md-contact-chips ng-model="ctrl.asyncContacts" md-contacts="ctrl.delayedQuerySearch($query)" md-contact-name="name" md-contact-image="image" md-contact-email="email" md-require-match="true" md-highlight-flags="i" filter-selected="ctrl.filterSelected" placeholder="To">
</md-contact-chips>
</md-content>
</div>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that can be foundin the LICENSE file at http://material.angularjs.org/HEAD/license.
-->
CSS
.chipsdemoContactChips md-content.autocomplete {
min-height: 250px; }
.chipsdemoContactChips md-content.autocomplete input {
min-width: 400px; }
.chipsdemoContactChips .md-item-text.compact {
padding-top: 8px;
padding-bottom: 8px; }
.chipsdemoContactChips .contact-item {
box-sizing: border-box; }
.chipsdemoContactChips .contact-item.selected {
opacity: 0.5; }
.chipsdemoContactChips .contact-item.selected h3 {
opacity: 0.5; }
.chipsdemoContactChips .contact-item .md-list-item-text {
padding: 14px 0;
max-width: 190px; }
.chipsdemoContactChips .contact-item .md-list-item-text h3 {
margin: 0 !important;
padding: 0;
line-height: 1.2em !important; }
.chipsdemoContactChips .contact-item .md-list-item-text h3, .chipsdemoContactChips .contact-item .md-list-item-text p {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden; }
@media (min-width: 960px) {
.chipsdemoContactChips .contact-item {
float: left;
width: 33%; } }
.chipsdemoContactChips md-contact-chips {
margin-bottom: 10px; }
.chipsdemoContactChips .md-chips {
padding: 5px 0 8px; }
.chipsdemoContactChips .fixedRows {
height: 250px;
overflow: hidden; }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that can be foundin the LICENSE file at http://material.angularjs.org/HEAD/license.
*/
JavaScript
(function () {
'use strict';
// If we do not have CryptoJS defined; import it
angular
.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('ContactChipDemoCtrl', DemoCtrl);
function DemoCtrl ($q, $timeout) {
var self = this;
var pendingSearch, cancelSearch = angular.noop;
var lastSearch;
self.allContacts = loadContacts();
self.contacts = [self.allContacts[0]];
self.asyncContacts = [];
self.filterSelected = true;
self.querySearch = querySearch;
self.delayedQuerySearch = delayedQuerySearch;
/**
* Search for contacts; use a random delay to simulate a remote call
*/
function querySearch (criteria) {
return criteria ? self.allContacts.filter(createFilterFor(criteria)) : [];
}
/**
* Async search for contacts
* Also debounce the queries; since the md-contact-chips does not support this
*/
function delayedQuerySearch(criteria) {
if ( !pendingSearch || !debounceSearch() ) {
cancelSearch();
return pendingSearch = $q(function(resolve, reject) {
// Simulate async search... (after debouncing)
cancelSearch = reject;
$timeout(function() {
resolve( self.querySearch(criteria) );
refreshDebounce();
}, Math.random() * 500, true)
});
}
return pendingSearch;
}
function refreshDebounce() {
lastSearch = 0;
pendingSearch = null;
cancelSearch = angular.noop;
}
/**
* Debounce if querying faster than 300ms
*/
function debounceSearch() {
var now = new Date().getMilliseconds();
lastSearch = lastSearch || now;
return ((now - lastSearch) < 300);
}
/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(contact) {
return...