Skip to content

Instantly share code, notes, and snippets.

@andybluntish
Last active June 7, 2018 23:22
Show Gist options
  • Save andybluntish/23b6923e1e3d5d8b7544f8bd3ee6b171 to your computer and use it in GitHub Desktop.
Save andybluntish/23b6923e1e3d5d8b7544f8bd3ee6b171 to your computer and use it in GitHub Desktop.
Accordion
import Ember from 'ember';
const { Controller } = Ember;
export default Controller.extend({
title: 'Accordion',
actions: {
say(msg) {
console.log('working...')
return new Ember.RSVP.Promise((y, n) => window.setTimeout(y, 1000))
.then(() => console.log(`Panel says: ${msg}`))
},
},
});
<h1>{{title}}</h1>
{{#accordion-list initialOpenIndex=0 as |list|}}
{{#list.item beforeClose=(action "say" "buh bye!") as |item|}}
<div class="header">
<h2 {{action item.toggle}}>Header 1</h2>
</div>
{{#if item.active}}
<div class="body">
<p>Some body content for item 1.</p>
<button {{action item.next}}>next</button>
</div>
{{/if}}
{{/list.item}}
{{#list.item beforeClose=(action "say" "buh bye!") as |item|}}
<div class="header">
<h2 {{action item.toggle}}>Header 2</h2>
</div>
{{#if item.active}}
<div class="body">
<p>Some body content for item 2.</p>
<button {{action item.next}}>next</button>
</div>
{{/if}}
{{/list.item}}
{{#list.item beforeClose=(action "say" "buh bye!") as |item|}}
<div class="header">
<h2 {{action item.toggle}}>Header 3</h2>
</div>
{{#if item.active}}
<div class="body">
<p>Some body content for item 3.</p>
<button {{action item.next}}>next</button>
</div>
{{/if}}
{{/list.item}}
{{#list.item beforeClose=(action "say" "buh bye!") as |item|}}
<div class="header">
<h2 {{action item.toggle}}>Header 4</h2>
</div>
{{#if item.active}}
<div class="body">
<p>Some body content for item 4.</p>
<button {{action item.next}}>next</button>
</div>
{{/if}}
{{/list.item}}
{{#list.item beforeClose=(action "say" "Oh! You're all done!") as |item|}}
<div class="header">
<h2 {{action item.toggle}}>Header 5</h2>
</div>
{{#if item.active}}
<div class="body">
<p>Some body content for item 5.</p>
<button {{action item.close}}>done</button>
</div>
{{/if}}
{{/list.item}}
{{/accordion-list}}
import Ember from 'ember';
const {
A,
Component,
get,
isEqual,
set
} = Ember;
export default Component.extend({
tagName: '',
items: null,
active: null,
initialOpenIndex: null,
init() {
this._super(...arguments)
set(this, 'items', A())
},
didInsertElement() {
const index = get(this, 'initialOpenIndex')
const itemKeys = get(this, 'items').mapBy('key')
const id = itemKeys.objectAt(index)
if (id) set(this, 'active', id)
},
actions: {
register(item) {
const items = get(this, 'items')
items.addObject(item)
set(this, 'items', items.uniq())
},
deregister(item) {
const items = get(this, 'items')
items.removeObject(item)
set(this, 'items', items.uniq())
},
open(key) {
const items = get(this, 'items')
const oldItem = items.findBy('key', get(this, 'active'))
const newItem = items.findBy('key', key)
if (oldItem) oldItem.send('onClose')
set(this, 'active', key);
if (newItem) newItem.send('onOpen')
},
close(key) {
const item = get(this, 'items').findBy('key', key)
if (item) item.send('onClose')
set(this, 'active', null);
},
next(key) {
const itemKeys = get(this, 'items').mapBy('key')
let newIndex = itemKeys.indexOf(key) + 1
if (newIndex > itemKeys.length - 1) newIndex = 0
const nextKey = itemKeys.objectAt(newIndex)
this.send('open', nextKey)
},
}
});
import Ember from 'ember';
const {
Component,
RSVP: { Promise },
computed,
get,
guidFor,
isEqual
} = Ember;
export default Component.extend({
tagName: '',
key: computed({
get() {
return guidFor(this);
}
}),
_active: null,
_open: null,
_close: null,
_next: null,
beforeClose() {},
afterClose() {},
isActive: computed('_active', {
get() {
const key = get(this, 'key')
const active = get(this, '_active')
return isEqual(key, active);
},
}).readOnly(),
didInsertElement() {
get(this, '_register')(this)
},
willDestroyElement() {
get(this, '_deregister')(this)
},
actions: {
open() {
const key = get(this, 'key')
const open = get(this, '_open')
open(key)
},
onOpen() {
const callback = get(this, 'onOpen')
if (callback) callback()
},
async close() {
const key = get(this, 'key')
const beforeClose = get(this, 'beforeClose')
const close = get(this, '_close')
const afterClose = get(this, 'afterClose')
await beforeClose()
close(key)
afterClose()
},
onClose() {
const callback = get(this, 'onClose')
if (callback) callback()
},
toggle() {
const key = get(this, 'key')
const isActive = get(this, 'isActive')
if (isActive) {
this.send('close')
} else {
this.send('open')
}
},
async next() {
const key = get(this, 'key')
const beforeClose = get(this, 'beforeClose')
const next = get(this, '_next')
const afterClose = get(this, 'afterClose')
await beforeClose()
next(key)
afterClose()
},
},
});
{{yield (hash
active=isActive
open=(action "open")
close=(action "close")
toggle=(action "toggle")
next=(action "next")
)}}
{{yield (hash item=(component "accordion-list/item"
_active=active
_register=(action "register")
_deregister=(action "deregister")
_open=(action "open")
_close=(action "close")
_next=(action "next")
))}}
{
"version": "0.13.0",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.16.2",
"ember-template-compiler": "2.16.2",
"ember-testing": "2.16.2"
},
"addons": {
"ember-data": "2.16.3"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment