Slide 1

Slide 1 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I CAN WRITE MY APP WITH NO HANDLEBARS Declarative Templating in Ember.js

Slide 2

Slide 2 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 LAUREN TAN SUGARPIRATE_ POTETO

Slide 3

Slide 3 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016

Slide 4

Slide 4 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 ZELDA

Slide 5

Slide 5 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016

Slide 6

Slide 6 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016

Slide 7

Slide 7 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS LOOK MA, NO HANDS!

Slide 8

Slide 8 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016

Slide 9

Slide 9 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016

Slide 10

Slide 10 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 https://www.youtube.com/watch?v=_ahvzDzKdB0

Slide 11

Slide 11 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 LARGE small

Slide 12

Slide 12 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS “A language design can no longer be a thing. It must be a pattern – a pattern for growth – a pattern for growing the pattern for defining the patterns that programmers can use for their real work and their main goal.” –Guy Steele

Slide 13

Slide 13 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS wat

Slide 14

Slide 14 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 15

Slide 15 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{get person propertyName}} {{t "user.edit.title"}} {{user-edit user=user}} {{if foo "bar" "baz"}}

Slide 16

Slide 16 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#shopping-cart items=items as |cart|}}
    {{#each cart.items as |item|}}
  • {{item.name}} - {{item.quantity}} x {{item.price}}
  • {{/each}}

{{cart.total}}
{{cart.checkout}} {{cart.empty}}
{{/shopping-cart}}

Slide 17

Slide 17 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 18

Slide 18 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 19

Slide 19 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 20

Slide 20 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS LOGICLESS TEMPLATES?

Slide 21

Slide 21 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS no logic extreme logic some logic

Slide 22

Slide 22 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS let Plates = require('plates'); let html = '
Old Value
'; let data = { test: 'New Value }; let output = Plates.bind(html, data);

Slide 23

Slide 23 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS let age = 18; hbs`{{if (gt age 21) Adult Kid}}`;

Slide 24

Slide 24 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS return
    {this.props.posts.map((post) => { return })}
;

Slide 25

Slide 25 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS IT DEPENDS™

Slide 26

Slide 26 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS SEPARATION OF CONCERNS

Slide 27

Slide 27 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{if (gt age 21) Adult Kid}}

Slide 28

Slide 28 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function gt([a, b]) { return a > b; } export default helper(gt);

Slide 29

Slide 29 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS AVOID PROGRAMMING IN THE TEMPLATE

Slide 30

Slide 30 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#unless (or (and (gte value 0) (lt value 0.0001)) (and (lt value 0) (not allowNegativeResults)))}} ... {{/unless}}

Slide 31

Slide 31 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export default Component.extend({ filteredItems: computed('items.@each.price', function() { // ... complicated logic }) });

Slide 32

Slide 32 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS
    {{#each (filter-by 'price' priceRange items) as |items|}}
  • {{item}}
  • {{/each}}
https://github.com/DockYard/ember-composable-helpers#filter-by

Slide 33

Slide 33 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS RULE OF LEAST POWER

Slide 34

Slide 34 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 35

Slide 35 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS “The "Rule of Least Power" suggests choosing the least powerful language suitable for a given purpose.”

Slide 36

Slide 36 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS least powerful most powerful

Slide 37

Slide 37 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS no logic extreme logic

Slide 38

Slide 38 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS
    {{#each items as |item|}}
  • {{item}}
  • {{/each}}

Slide 39

Slide 39 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS
    {this.props.items.map((item) => {
  • {item}
  • })}
;

Slide 40

Slide 40 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Greetings!

Hello {{name}}, and welcome.

Slide 41

Slide 41 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Greetings!

"Hello " "Jim Bob" ", and welcome."

Slide 42

Slide 42 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS el.childNodes; // ["Hello ", "Jim Bob", ", and welcome."]

Slide 43

Slide 43 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 44

Slide 44 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS KEYWORD VS HELPER

Slide 45

Slide 45 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS action component concat debugger each each-in get hash if input link-to loc log mut outlet partial query-params render textarea unbound unless with

Slide 46

Slide 46 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function foo([model, value], { async }) { // .. } export default helper(foo); {{foo model "abc" async=true}}

Slide 47

Slide 47 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 48

Slide 48 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS –Harold Abelson “Programs are meant to be read by humans and only incidentally for computers to execute.”

Slide 49

Slide 49 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS –Unknown “Every line of code is a liability. The code that's easiest to maintain is code that was never written.”

Slide 50

Slide 50 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS Hello World Hello, Example. Today's date and time is {{now}}.

Slide 51

Slide 51 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS page = Page(); head = new Head(); title = new Title(); title.setText("Hello World") head.add(title); page.add(head); body = new Body(); preamble = new StringBuffer(); preamble.append("Hello, Example. Today's date and time is "); preamble.append(Time.now().toString()); preamble.append("."); body.add(preamble.toString()); page.add(body);

Slide 52

Slide 52 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS DECLARATIVE TEMPLATING

Slide 53

Slide 53 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS no logic extreme logic some logic

Slide 54

Slide 54 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#each filteredEmployees as |employee|}} ... {{/each}}

Slide 55

Slide 55 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export default Component.extend({ employeeFilter: 'active', filteredEmployees: filter('employees', function() { let filter = get(this, 'employeeFilter'); return get(this, 'employees').filterBy('type', filter); }) });

Slide 56

Slide 56 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#each-in groupedEmployees as |group employees|}} ... {{/each-in}}

Slide 57

Slide 57 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export default Component.extend({ employeeGroupBy: 'role', filteredEmployees: /* ... */, groupedEmployees: computed('employeeGroupBy', 'filteredEmployees', function() { // ... complicated logic }) });

Slide 58

Slide 58 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS https://github.com/DockYard/ember-composable-helpers {{#with (filter-by "type" employeeFilter employees) as |filteredEmployees|}} {{#each-in (group-by employeeGroupBy filteredEmployees) as |group employees|}} ... {{/each-in}} {{/with}}

Slide 59

Slide 59 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS https://github.com/DockYard/ember-composable-helpers {{#each-in (group-by employeeGroupBy (filter-by "type" employeeFilter employees)) as |group employees|}} ... {{/each-in}}

Slide 60

Slide 60 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 61

Slide 61 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS IT DEPENDS™

Slide 62

Slide 62 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS no logic extreme logic some logic

Slide 63

Slide 63 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 64

Slide 64 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#form-for person as |f|}} {{f.text-field "firstName"}} {{f.text-field "lastName"}} {{f.date-field "birthDate"}} {{f.submit "Save"}} {{/form-for}} https://github.com/martndemus/ember-form-for

Slide 65

Slide 65 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 66

Slide 66 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 67

Slide 67 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS –Jiro Ono “In order to make delicious food, you must eat delicious food. […] Without good taste, you can’t make good food.”

Slide 68

Slide 68 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS GOOD TASTE, GOOD CODE

Slide 69

Slide 69 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS EMBERGER HELPERS

Slide 70

Slide 70 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS HELPER PURITY

Slide 71

Slide 71 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{capitalize "hello"}} {{capitalize "hello"}}

Slide 72

Slide 72 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function add([a, b]) { return a + b; } export default helper(add);

Slide 73

Slide 73 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

1 + 1 = {{add 1 1}}

Slide 74

Slide 74 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS let x = 0; export function add([a]) { return x += a; } export default helper(add);

Slide 75

Slide 75 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS const sortMap = { ascending(a, b) { return a - b; }, descending(a, b) { return b - a; } }; export function sort([order, items]) { let sortFn = sortMap[order] || K; items.sort(sortFn); return items; } export default helper(append);

Slide 76

Slide 76 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 77

Slide 77 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS Numbers: {{numbers}} Sorted: {{sort "ascending" numbers}} Numbers: {{numbers}} https://ember-twiddle.com/717d4c5f774d0b2822e853d67ef7c3a9?openFiles=templates.application.hbs%2C

Slide 78

Slide 78 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 79

Slide 79 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS EMBER-CHANGESET https://github.com/DockYard/ember-changeset

Slide 80

Slide 80 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 81

Slide 81 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function changeset(obj, validateFn, validationMap) { return EmberObject.extend({ // changeset implementation }); } export default class Changeset { constructor() { return changeset(...arguments).create(); } }

Slide 82

Slide 82 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function changeset([model, validationMap]) { if (isObject(validationMap)) { return new Changeset(model, lookupValidator(validationMap), validationMap); } return new Changeset(model, validationMap); } export default helper(changeset);

Slide 83

Slide 83 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{dummy-form changeset=(changeset user EmployeeValidations) submit=(action "submit") rollback=(action "rollback") }} https://bit.ly/ember-changeset-demo

Slide 84

Slide 84 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS RETURN VALUES

Slide 85

Slide 85 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS STRINGS, NUMBERS, BOOLEANS

Slide 86

Slide 86 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function join([separator, ...words]) { return words.join(separator); } export default helper(join); export function sum([...values]) { return values.reduce((acc, curr) => { return acc + curr; }, 0); } export default helper(join); export function gt([a, b]) { return a > b; } export default helper(gt); {{join "-" "hello" "world"}} {{sum 1 2 3}} {{gt 1 2}}

Slide 87

Slide 87 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS ARRAYS

Slide 88

Slide 88 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function repeat([length, value]) { if (typeOf(length) !== 'number') { return [value]; } return Array.apply(null, { length }).map(() => value); } export default helper(repeat); https://github.com/DockYard/ember-composable-helpers#repeat

Slide 89

Slide 89 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#each (repeat 3 "Developers") as |text|}} {{text}} {{/each}}

Slide 90

Slide 90 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS OBJECTS

Slide 91

Slide 91 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#with (changeset user userValidations) as |changeset|}} {{input value=changeset.firstName}} Save {{/with}}

Slide 92

Slide 92 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{#with (hash bar=(component "hello-world")) as |foo|}} {{foo.bar name="Jim Bob"}} {{/with}}

Slide 93

Slide 93 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{complex-component ui=(hash map=(component "user-map") sidebar=(component "user-sidebar") form=(component "user-form")) }}

Slide 94

Slide 94 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{ui.sidebar user=user}} {{ui.map lat=user.lat lng=user.lng}} {{ui.form user=user}}

Slide 95

Slide 95 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function registerDummyComponent(context, name = 'dummy-component', opts = {}) { let owner = getOwner(context); let options = assign({ tagName: 'dummy' }, opts); let DummyComponent = Component.extend(options); unregisterDummyComponent(context, name); owner.register(`component:${name}`, DummyComponent); } export function unregisterDummyComponent(context, name = 'dummy-component') { let owner = getOwner(context); if (owner.resolveRegistration(`component:${name}`)) { owner.unregister(`component:${name}`); } }

Slide 96

Slide 96 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS test('it does something', function(assert) { registerDummyComponent(this); this.set('user', { firstName: 'Jim', lat: 51.5074, lng: 0.1278 }); this.on('submit', K); this.render(hbs` {{complex-component ui=(hash map=(component "dummy-component") sidebar=(component "dummy-component") form=(component "dummy-component")) }} `); assert.ok(...); });

Slide 97

Slide 97 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS FUNCTIONS

Slide 98

Slide 98 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function toggle([obj, prop]) { return function() { set(obj, prop, !get(obj, prop)); }; } https://github.com/DockYard/ember-composable-helpers#toggle

Slide 99

Slide 99 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{if isExpanded "I am expanded" "I am not"}}

Slide 100

Slide 100 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS 1-Click Buy https://github.com/DockYard/ember-composable-helpers#pipe

Slide 101

Slide 101 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export function pipe(actions = []) { return function(...args) { return actions.reduce((acc, curr, idx) => { if (idx === 0) { return curr(...args); } return invokeFunction(acc, curr); }, undefined); }; } export default helper(pipe);

Slide 102

Slide 102 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS CLASS BASED HELPER

Slide 103

Slide 103 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS {{t "user.edit"}}

Slide 104

Slide 104 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS export default Helper.extend({ localesService: inject.service('locales'), currentLocale: readOnly('localesService.currentLocale'), compute([key]) { let currentLocale = get(this, 'currentLocale'); return get(this, 'localesService').lookup(currentLocale, key); }, localeDidChange: observer('currentLocale', function() { this.recompute(); }) });

Slide 105

Slide 105 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS

Slide 106

Slide 106 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 COMPUTED VS HELPER

Slide 107

Slide 107 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 COMPUTEDS

Slide 108

Slide 108 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 export default Component.extend({ @computed('payment', 'rate', 'periods') annuity(payment, rate, periods) { let factor = ((1 - Math.pow(1 + rate, -periods)) / rate); return payment * factor; } });

Slide 109

Slide 109 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 HELPERS

Slide 110

Slide 110 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 {{#each (repeat 3) as |nil index|}}
{{!some HTML block}}
{{/each}} https://github.com/DockYard/ember-composable-helpers#repeat

Slide 111

Slide 111 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 {{#unless (or (and (gte value 0) (lt value 0.0001)) (and (lt value 0) (not allowNegativeResults)))}} ... {{/unless}}

Slide 112

Slide 112 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS TL;DR

Slide 113

Slide 113 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 114

Slide 114 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 115

Slide 115 text

EMBERCAMP 2016 I CAN WRITE MY APP WITH NO HANDLEBARS I. Templates are Data II. Your UI as a Language III.Helper Best Practices

Slide 116

Slide 116 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 LAUREN TAN SUGARPIRATE_ POTETO

Slide 117

Slide 117 text

I CAN WRITE MY APP WITH NO HANDLEBARS EMBERCAMP 2016 LAUREN TAN SUGARPIRATE_ POTETO Thanks {{name}}!