56 lines
2.1 KiB
JavaScript
56 lines
2.1 KiB
JavaScript
|
import Component from '@ember/component';
|
||
|
import { isPresent } from '@ember/utils';
|
||
|
import { get, set, computed, defineProperty } from '@ember/object';
|
||
|
import layout from '../templates/components/block-slot';
|
||
|
import Slots from '../mixins/slots';
|
||
|
import YieldSlot from './yield-slot';
|
||
|
const BlockSlot = Component.extend({
|
||
|
layout,
|
||
|
tagName: '',
|
||
|
didInsertElement: function() {
|
||
|
const slottedComponent = this.nearestOfType(Slots);
|
||
|
if (!slottedComponent._isRegistered(this._name)) {
|
||
|
slottedComponent._activateSlot(this._name);
|
||
|
set(this, 'slottedComponent', slottedComponent);
|
||
|
return;
|
||
|
}
|
||
|
const yieldSlot = this.nearestOfType(YieldSlot);
|
||
|
if (yieldSlot) {
|
||
|
set(this, '_yieldSlot', yieldSlot);
|
||
|
// The slotted component will yield multiple times - once to register
|
||
|
// the activate slots and once more per active slot - only display this
|
||
|
// block when its associated slot is the one yielding
|
||
|
const isTargetSlotYielding = yieldSlot._name === this._name;
|
||
|
set(this, 'isTargetSlotYielding', isTargetSlotYielding);
|
||
|
|
||
|
// If the associated slot has block params, create a computed property
|
||
|
// for each block param. Technically this could be an unlimited, but
|
||
|
// hbs lacks a spread operator so params are currently limited to 9
|
||
|
// (see the yield in the block-slot template)
|
||
|
//
|
||
|
// Spread PR: https://github.com/wycats/handlebars.js/pull/1149
|
||
|
if (isTargetSlotYielding && isPresent(yieldSlot._blockParams)) {
|
||
|
// p0 p1 p2...
|
||
|
yieldSlot._blockParams.forEach((param, index) => {
|
||
|
defineProperty(this, `p${index}`, computed.readOnly(`_yieldSlot._blockParams.${index}`));
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
willDestroyElement: function() {
|
||
|
const slottedComponent = get(this, 'slottedComponent');
|
||
|
if (slottedComponent) {
|
||
|
// Deactivate the yield slot using the slots interface when the block
|
||
|
// is destroyed to allow the yield slot default {{else}} to take effect
|
||
|
// dynamically
|
||
|
slottedComponent._deactivateSlot(this._name);
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
|
||
|
BlockSlot.reopenClass({
|
||
|
positionalParams: ['_name'],
|
||
|
});
|
||
|
|
||
|
export default BlockSlot;
|