Skip to content

Instantly share code, notes, and snippets.

@patocallaghan
Last active March 2, 2022 12:30
Show Gist options
  • Save patocallaghan/01856d13489b2f9a6058a6c29f86b523 to your computer and use it in GitHub Desktop.
Save patocallaghan/01856d13489b2f9a6058a6c29f86b523 to your computer and use it in GitHub Desktop.
Ember Octane
import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class HtmlDemo extends Component {
@action
updateFirstName(event) {
// This will throw an error because this.args is not mutable
this.args.firstName = event.target.value;
}
}
import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class HtmlDemo extends Component {
//Event Handlers
@action
handleMouseDown(event) {
console.log('mouseDown');
}
@action
handleClick(value, event) {
console.log('click', value, event.target.tagName);
}
@action
handleMouseUp(event) {
console.log('mouseUp');
}
}
import Component from '@glimmer/component';
/*
LIFECYCLE HOOKS
* constructor
* willDestroy
* modifiers - https://github.com/ember-modifier/ember-modifier
* resources - https://github.com/NullVoxPopuli/ember-resources
*/
export default class LifecycleHooks extends Component {
constructor() {
super(...arguments);
console.log('LIFECYCLE: constructor');
}
willDestroy() {
super.willDestroy(...arguments);
console.log('LIFECYCLE: willDestroy');
}
}
/*
* Reactivity based on Autotracking
* Read-only by default
* It's just JS: new, static, getters, some decorators
* getters vs computed
* new Object() vs Object.create()
* constructor vs init
* static vs constructor
**/
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
class User {
firstName;
@tracked lastName;
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
static someFunction() {
console.log('Called from User');
}
}
/* ============================== */
export default class ApplicationController extends Controller {
@tracked showLifecycleComponent = false;
@tracked showHtmlDemoComponent = false;
@tracked showDataFlowComponent = false;
constructor() {
super(...arguments);
this.user = new User('Travis','Bickle');
// static function
User.someFunction();
}
@action
updateFirstName(event) {
this.user.firstName = event.target.value;
}
@action
updateLastName(event) {
this.user.lastName = event.target.value;
}
@action
toggleComponent(property) {
this[property] = !this[property];
}
}
import { modifier } from 'ember-modifier';
export default modifier((element) => {
element.focus();
});
<h1>Ember Octane</h1>
<label>
First name
<input
type="text"
value={{this.user.firstName}}
{{on "input" this.updateFirstName}}
/>
</label>
<label>
Last name
<input
type="text"
value={{this.user.lastName}}
{{on "input" this.updateLastName}}
/>
</label>
<hr>
User first name: {{this.user.firstName}}<br>
User last name: {{this.user.lastName}}<br>
User full name: {{this.user.fullName}}<br>
<hr>
<label>
Show lifecycle component
<input
type="checkbox"
{{on "change" (fn this.toggleComponent "showLifecycleComponent")}}
checked={{this.showLifecycleComponent}}
/>
</label>
<br>
{{#if this.showLifecycleComponent}}
<LifecycleHooks />
{{/if}}
<hr>
<label>
Show html component
<input
type="checkbox"
{{on "change" (fn this.toggleComponent "showHtmlDemoComponent")}}
checked={{this.showHtmlDemoComponent}}
/>
</label>
<br>
{{#if this.showHtmlDemoComponent}}
<hr>
<HtmlDemo
class="four"
data-external-attribute
/>
{{/if}}
<hr>
<label>
Show data flow component
<input
type="checkbox"
{{on "change" (fn this.toggleComponent "showDataFlowComponent")}}
checked={{this.showDataFlowComponent}}
/>
</label>
<br>
{{#if this.showDataFlowComponent}}
<hr>
<DataFlow
@firstName={{this.user.firstName}}
@lastName={{this.user.lastName}}
@onUpdate={{this.updateLastName}}
class="x"
/>
{{/if}}
{{!--
* Namespaced arguments - clear separation between local state and passed in arguments
* One way data-flow (see args error)
* Data Down, Actions Up
--}}
<h2>Data flow component</h2>
this.lastName: {{this.lastName}}<br>
@lastName: {{@lastName}}<br>
<br>
<label>
Update this.args.lastName
<input
type="text"
value={{@lastName}}
{{on "input" this.updateFirstName}}
/>
</label>
<br>
<label>
Update @lastName using a passed in action
<input
type="text"
value={{@lastName}}
{{on "input" @onUpdate}}
/>
</label>
{{!--
Glimmer Component
* All the content is in the template
* "...attributes" splattributes - Render passed in HTML attributes
* "on" + "fn" helpers - see JS
--}}
<div
class="one two three"
data-internal-attribute
...attributes
>
<h2 ...attributes>Html demo</h2>
<button
{{on "mousedown" this.handleMouseDown}}
{{on "click" (fn this.handleClick "custom value")}}
{{on "mouseup" this.handleMouseUp}}
>
Click me
</button>
</div>
{{!-- See JS --}}
<h2>Lifecycle hooks</h2>
<input {{focus}}/>
{
"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",
"ember-modifier": "2.1.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment