Skip to content

Instantly share code, notes, and snippets.

@jede
Last active April 26, 2021 09:24
Show Gist options
  • Save jede/0578d336521f996eea69ceb2f7de1d85 to your computer and use it in GitHub Desktop.
Save jede/0578d336521f996eea69ceb2f7de1d85 to your computer and use it in GitHub Desktop.
Glimmer updated collection
import Component from '@glimmer/component'
import { action } from '@ember/object'
export default class CategoriesFilterSubComponentsComponent extends Component {
@action toggle(category) {
const sel = this.args.selected || []
if (sel.includes(category)) {
this.args.changed(sel.without(category))
} else {
this.args.changed(sel.concat([category]))
}
}
}
import Component from '@glimmer/component'
import { action } from '@ember/object'
export default class CategoriesFilterComponent extends Component {
get options() {
const selected = this.args.selected || []
return this.args.categories.map(({ id, name }) => ({
id,
name,
selected: selected.some((c) => c.id === id),
}))
}
@action toggle({ id, selected }) {
const sel = this.args.selected || []
const category = this.args.categories.find((c) => c.id === id)
if (selected) {
this.args.changed(sel.without(category))
} else {
this.args.changed(sel.concat([category]))
}
}
}
import Component from '@glimmer/component'
import { action } from '@ember/object'
export default class CategoriesFilterButtonComponent extends Component {
get isSelected() {
const selected = this.args.selected || []
return selected.includes(this.args.category)
}
@action toggle() {
const category = this.args.category
const selected = this.args.selected || []
if (this.isSelected) {
this.args.changed(selected.without(category))
} else {
this.args.changed(selected.concat([category]))
}
}
}
import Component from '@glimmer/component'
import { action } from '@ember/object'
export default class CategoriesFilterComponent extends Component {
@action toggle(category) {
const sel = this.args.selected || []
if (sel.includes(category)) {
this.args.changed(sel.without(category))
} else {
this.args.changed(sel.concat([category]))
}
}
}
import Controller from '@ember/controller';
import { action } from '@ember/object'
import { tracked } from '@glimmer/tracking'
export default class ApplicationController extends Controller {
@tracked categories = [{id: 1, name: 'Food'}, {id: 2, name: 'Drinks'}, {id: 3, name: 'Snacks'}]
@tracked selectedCategories = []
@tracked exampleSelected = false
@action categoriesSelected(selected) {
this.selectedCategories = selected
}
@action toggleExample() {
this.exampleSelected = !this.exampleSelected
}
}
import { helper } from '@ember/component/helper';
export default helper(function includes([needle, haystack], options) {
return haystack.includes(needle)
});
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
button {
transition: all 1s cubic-bezier(0.68, -0.55, 0.27, 1.55);
transform: rotate3d(0, 0, 0, 0);
border: none;
background-color: #03a9f4;
text-transform: uppercase;
font-weight: bold;
letter-spacing: 0.03em;
color: white;
padding: 5px 15px;
border-radius: 15px;
margin: 1em 0.2em;
user-select: none;
}
.selected {
transform: rotate3d(1, 1, 1, 360deg);
background-color: #0a709f;
}
Select some categories (but no transition occurs): <CategoriesFilterWithoutHelper @categories={{this.categories}} @selected={{this.selectedCategories}} @changed={{this.categoriesSelected}}/>
Transition works but uses (ugly and bad practice?) custom <strong>includes</strong> helper: <CategoriesFilter @categories={{this.categories}} @selected={{this.selectedCategories}} @changed={{this.categoriesSelected}}/>
Transition works but uses a <b>sub component</b> (with lots of passing props around, and hard to follow logic) for the button: <CategoriesFilterSubComponents @categories={{this.categories}} @selected={{this.selectedCategories}} @changed={{this.categoriesSelected}}/>
Expected transition:
<div>
<button class={{if exampleSelected 'selected'}} {{on 'click' (fn this.toggleExample) }}>Try me</button>
</div>
<div>
{{#each this.args.categories as |category|}}
<CategoriesFilter::Button @category={{category}} @selected={{@selected}} @changed={{@changed}}/>
{{/each}}
</div>
<div>
{{#each this.options as |option|}}
<button class={{if option.selected 'selected'}} {{on 'click' (fn this.toggle option) }}>{{option.name}}</button>
{{/each}}
</div>
<button class={{if isSelected 'selected'}} {{on 'click' (fn this.toggle) }}>{{@category.name}}</button>
<div>
{{#each this.args.categories as |category|}}
<button class={{if (includes category this.args.selected) 'selected'}} {{on 'click' (fn this.toggle category) }}>{{category.name}}</button>
{{/each}}
</div>
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment