SlideShare une entreprise Scribd logo
1  sur  90
Télécharger pour lire hors ligne
The Hidden Power
of HTMLBars
or, Scope in Ember.js Templates
EmberCamp 2015
@mixonic
Ember.js Core Team
201 Created
Consultants in NewYork City
BrooklynLondon
BrooklynLondon
BrooklynLondon
BrooklynLondon
BrooklynLondon
Chips Fries
BrooklynLondon
Chips Fries
Crisps Chips
BrooklynLondon
Chips Fries
Crisps Chips
BrooklynLondon
Chips Fries
Crisps Chips
Fries
BrooklynLondon
Chips Fries
Crisps Chips
Fries Crisps
BrooklynLondon
Chips Fries
Crisps Chips
Fries Crisps
Metric
BrooklynLondon
Chips Fries
Crisps Chips
Fries Crisps
Metric
FREEDOM
Chips
Crisps
Fries
?
“Hey, look at those chips”
“chips”
? ?
? ?
?
? ?
?
BrooklynLondon
42-48˚ F50-57˚ F
10–14˚ C 5-9˚ C
Scope
EntityScope + Rules + Label
EntityScope + Rules + Label
cold beer
cold beers

are served in NYC
“chips”
thin, flat, and fried

slices of potato
1 {{! app/templates/components/british-pub.hbs }}
2 <h2>{{name}} Menu</h2>
3 <ul>
4 {{#each snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
1 {{! app/templates/components/british-pub.hbs }}
2 <h2>{{name}} Menu</h2>
3 <ul>
4 {{#each snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
Label
1 {{! app/templates/components/british-pub.hbs }}
2 <h2>{{name}} Menu</h2>
3 <ul>
4 {{#each snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
Scope
Rules
1. Dynamic Scope
2. Lexical (Static) Scope
Dynamic Scope
“In languages with dynamic
scope the name resolution
depends upon the program state
when the name is encountered
which is determined by the
execution context or calling
context.”
Wikipedia
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name;
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # local_sub: Fry
6 # show_name: Crisp
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name;
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name;
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp";
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # local_sub: Fry
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # local_sub: Fry
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # local_sub: Fry
6
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # local_sub: Fry
6 # show_name: Crisp
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # local_sub: Fry
6 # show_name: Crisp
7 sub local_sub {
8 local $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "local_sub: ", &local_sub(), "n";
18 print "show_name: ", &show_name(), "n";
What context do you
need to understand the
value of $name?
“In languages with dynamic
scope the name resolution
depends upon the program state
when the name is encountered
which is determined by the
execution context or calling
context.”
Wikipedia
Lexical (Static) Scope
“In languages with lexical scope (also
called static scope), name resolution
depends on the location in the source
code and the lexical context, which is
defined by where the named variable or
function is defined.”
Wikipedia
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # my_sub: Crisp
6 # show_name: Crisp
7 sub my_sub {
8 my $name = "Fry";
9 return show_name();
10 }
11
12 sub show_name {
13 return $name;
14 }
15
16 print "$name: $namen";
17 print "my_sub: ", &my_sub(), "n";
18 print "show_name: ", &show_name(), "n";
1 #!/usr/bin/perl -w
2 use strict;
3
4 our $name; # $name: Crisp
5 $name = "Crisp"; # my_sub: Fry
6 # show_name: Crisp
7 sub my_sub {
8 my $name = "Fry";
9 return show_name($name);
10 }
11
12 sub show_name {
13 return shift || $name;
14 }
15
16 print "$name: $namen";
17 print "my_sub: ", &my_sub(), "n";
18 print "show_name: ", &show_name(), "n";
“In languages with lexical scope (also
called static scope), name resolution
depends on the location in the source
code and the lexical context, which is
defined by where the named variable or
function is defined.”
Wikipedia
Benefits of Static Scope
1. Possible to optimize at compile time
2. Easier for developers to read
3. JavaScript and pretty much all
languages use it
1 {{! app/templates/index.hbs }}
2 <h2>{{name}} Menu</h2>
3 <ul>
4 {{#view 'localized-menu' model}}
5 <li>{{name}}: {{model.price}}</li>
6 {{/view}}
7 </ul>
Ember 1.x
1 {{! app/templates/index.hbs }}
2 <h2>{{name}} Menu</h2>
3 <ul>
4 {{#view 'localized-menu' model}}
5 <li>{{name}}: {{model.price}}</li>
6 {{/view}}
7 </ul>
Ember 1.x
• Index controller
• Index controller model
• New context from
localized-menu
• Helper
Dynamic
1 {{! app/templates/index.hbs }}
2 <h2>{{name}} Menu</h2>
3 <ul>
4 {{#view 'localized-menu' model}}
5 <li>{{name}}: {{model.price}}</li>
6 {{/view}}
7 </ul>
Ember 1.x Ember 2.x
1 {{! app/templates/index.hbs }}
2 <h2>{{model.name}} Menu</h2>
3 <ul>
4 {{#each model.snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
1 {{! app/templates/index.hbs }}
2 <h2>{{model.name}} Menu</h2>
3 <ul>
4 {{#each model.snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
Ember 2.x
• Property on packet
• Helper
Static
1 {{! app/templates/index.hbs }}
2 <h2>{{model.name}} Menu</h2>
3 <ul>
4 {{#each model.snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
Ember 2.x
• Property on packet
• Helper
Static
1 {{! app/templates/index.hbs }}
2 <h2>{{model.name}} Menu</h2>
3 <ul>
4 {{#each model.snacks as |packet|}}
5 <li>{{packet.name}}: {{packet.price}}</li>
6 {{/each}}
7 </ul>
1 function buildIndex(model) {
2 let html = `<h2>${model.name} Menu</h2>`;
3 html += '<ul>';
4 model.snacks.forEach(packet => {
5 html += `<li>
6 ${packet.name}: ${packet.price}
7 </li>`;
8 });
9 html += '</ul>';
10 return html;
11 }
Ember 2.x
Creating a template system with static
scoping is an intentional goal of
HTMLBars/Glimmer, and directs the
underlying architecture.
Tools for Static Scope
Closures
Closures
1 function generateSayName() {
2 let name = 'Chips';
3 return function() {
4 alert(name);
5 };
6 }
7
8 var sayName = generateSayName();
9
10 console.log(sayName()); // alerts: Chips
1 function generateSayName() {
2 let name = 'Chips';
3 return function() {
4 alert(name);
5 };
6 }
7
8 var sayName = generateSayName();
9
10 console.log(sayName()); // alerts: Chips
Closures
Ember Actions as Closures
1 {{#with (action 'alert' name) as |sayName|}}
2 <button {{action sayName}}>Say the name!</button>
3 {{/with}}
Ember Actions as Closures
1 {{! app/templates/components/generate-say-name.hbs }}
2 {{yield (action 'alert' name)}}
1 {{! app/templates/index.hbs }}
2 {{#generate-say-name name='Chip' as |sayName|}}
3 <button {{action sayName}}>Say the name!</button>
4 {{/generate-say-name}}
Ember Actions as Closures
1 {{! app/templates/components/generate-say-name.hbs }}
2 {{yield (hash
3 sayBritish=(action 'alert' 'Crisp')
4 sayAmerican=(action 'alert' 'Chip')
5 )}}
1 {{! app/templates/index.hbs }}
2 {{#generate-say-name as |ux|}}
3 <button {{action ux.sayBritish}}>Say the name!</button>
4 {{/generate-say-name}}
Ember actions are just
JavaScript functions.
Ember Components as Closures
1 {{! app/templates/index.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{#ux.sayBritish}}Say the name!{{/ux.sayBritish}}
4 {{/generate-say-name}}
1 {{! app/templates/components/generate-say-name.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-name-button' name='Crisp')
4 sayAmerican=(component 'say-name-button' name='Chip')
5 )}}
Pods, Local Lookup, and Closures
bit.ly/pods-local-lookup
speakerdeck.com/rwjblue/a-tale-of-two-pods
Pods
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 routes/
6 index/
7 template.hbs
Pods
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 routes/
6 index/
7 template.hbs
1 {{! app/routes/index/template.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}}
4 {{/generate-say-name}}
Pods
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 routes/
6 index/
7 template.hbs
1 {{! app/routes/index/template.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}}
4 {{/generate-say-name}}
1 {{! app/components/generate-say-name/template.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-name-button' name='Crisp')
4 sayAmerican=(component 'say-name-button' name='Chip')
5 )}}
Pods
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 routes/
6 index/
7 template.hbs
1 {{! app/components/generate-say-name/template.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-name-button' name='Crisp')
4 sayAmerican=(component 'say-name-button' name='Chip')
5 )}}
Pods
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 routes/
6 index/
7 template.hbs
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 say-name-button/
6 template.hbs
7 routes/
8 index/
9 template.hbs
1 {{! app/components/generate-say-name/template.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-name-button' name='Crisp')
4 sayAmerican=(component 'say-name-button' name='Chip')
5 )}}
Pods
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
1 {{! app/components/generate-say-name/template.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-name-button' name='Crisp')
4 sayAmerican=(component 'say-name-button' name='Chip')
5 )}}
Local Lookup
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
1 {{! app/components/generate-say-name/template.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-name-button' name='Crisp')
4 sayAmerican=(component 'say-name-button' name='Chip')
5 )}}
Local Lookup
1 {{! app/routes/index/template.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}}
4 {{/generate-say-name}}
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
Local Lookup
1 {{! app/routes/index/template.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}}
4 {{/generate-say-name}}
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
Local Lookup
1 {{! .../say-name-button/template.hbs }}
2 <button {{action 'alert' name}}>{{yield}}</button>
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
Local Lookup
1 {{! .../say-name-button/template.hbs }}
2 <button {{action 'alert' name}}>{{yield}}</button>
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
Local Lookup
1 {{! app/routes/index/template.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}}
4 {{/generate-say-name}}
1 app/
2 components/
3 generate-say-name/
4 template.hbs
5 components/
6 say-name-button/
7 template.hbs
8 routes/
9 index/
10 template.hbs
Local Lookup
bit.ly/pods-local-lookup
speakerdeck.com/rwjblue/a-tale-of-two-pods
Tools for Static Scope
Partial Applications
Partial Application
1 function generateSayName() {
2 let name = 'Chips';
3 return function(honorific) {
4 alert(`${honorific} ${name}`);
5 };
6 }
7
8 var sayName = generateSayName();
9
10 console.log(sayName('Mr.')); // logs: Mr. Chips
1 function generateSayName() {
2 let name = 'Chips';
3 return function(honorific) {
4 alert(`${honorific} ${name}`);
5 };
6 }
7
8 var sayName = generateSayName();
9
10 console.log(sayName('Mr.')); // logs: Mr. Chips
Partial Application
1 function generateSayName() {
2 let name = 'Chips';
3 return function(honorific) {
4 alert(`${honorific} ${name}`);
5 };
6 }
7
8 var sayName = generateSayName();
9
10 console.log(sayName('Mr.')); // logs: Mr. Chips
Partial Application
Ember Actions with Partial Application
1 {{! app/templates/index.hbs }}
2 {{#generate-say-name as |sayName|}}
3 <button {{action sayName 'Mr.'}}>Say the name!</button>
4 {{/generate-say-name}}
1 {{! app/templates/components/generate-say-name.hbs }}
2 {{yield (action 'alert' 'Crisps')}}
Ember Actions with Partial Application
1 {{! app/templates/index.hbs }}
2 {{#generate-say-name as |sayName|}}
3 <button {{action sayName 'Mr.'}}>Say the name!</button>
4 {{/generate-say-name}}
1 {{! app/templates/components/generate-say-name.hbs }}
2 {{yield (action 'alert' 'Crisps')}}
1 actions: {
2 alert(name, honorific) {
3 console.log(`${honorific} ${name}`);
4 }
5 }
Ember Components with Partial Application
1 {{! app/templates/components/generate-say-name.hbs }}
2 {{yield (hash
3 sayBritish=(component 'say-button-name' honorific='MP')
4 sayAmerican=(component 'say-button-name' honorific='Rep')
5 )}}
1 {{! app/templates/index.hbs }}
2 {{#generate-say-name as |ux|}}
3 {{ux.sayBritish name='Chips'}}
4 {{ux.sayAmerican honorific='Mr.' name='Fry'}}
5 {{/generate-say-name}}
1 {{! app/templates/components/say-button-name.hbs }}
2 <button {{action 'alert' name honorific}}>Say the Name</button>
Tools for Static Scope
Recursion?!
emberjs.jsbin.com/fubutusejo/1/edit?html,js,output
Ember templates have the scoping rules
and consistency of a real language.
Develop using the patterns and tools you
would use in a real language.
Thanks!
@mixonic

Contenu connexe

Tendances

Tendances (20)

Pop3ck sh
Pop3ck shPop3ck sh
Pop3ck sh
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLs
 
The Perl6 Type System
The Perl6 Type SystemThe Perl6 Type System
The Perl6 Type System
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16
 
Learning Perl 6 (NPW 2007)
Learning Perl 6 (NPW 2007)Learning Perl 6 (NPW 2007)
Learning Perl 6 (NPW 2007)
 
pts_ldap
pts_ldappts_ldap
pts_ldap
 
Perl6 in-production
Perl6 in-productionPerl6 in-production
Perl6 in-production
 
PHP code examples
PHP code examplesPHP code examples
PHP code examples
 
Perl6 one-liners
Perl6 one-linersPerl6 one-liners
Perl6 one-liners
 
Créer une base NoSQL en 1 heure
Créer une base NoSQL en 1 heureCréer une base NoSQL en 1 heure
Créer une base NoSQL en 1 heure
 
Perl6 grammars
Perl6 grammarsPerl6 grammars
Perl6 grammars
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongers
 
I, For One, Welcome Our New Perl6 Overlords
I, For One, Welcome Our New Perl6 OverlordsI, For One, Welcome Our New Perl6 Overlords
I, For One, Welcome Our New Perl6 Overlords
 
Bag of tricks
Bag of tricksBag of tricks
Bag of tricks
 
PHP Tips & Tricks
PHP Tips & TricksPHP Tips & Tricks
PHP Tips & Tricks
 
Advanced modulinos trial
Advanced modulinos trialAdvanced modulinos trial
Advanced modulinos trial
 
ZeroMQ Is The Answer
ZeroMQ Is The AnswerZeroMQ Is The Answer
ZeroMQ Is The Answer
 
03 tk2123 - pemrograman shell-2
03   tk2123 - pemrograman shell-203   tk2123 - pemrograman shell-2
03 tk2123 - pemrograman shell-2
 
Get into the FLOW with Extbase
Get into the FLOW with ExtbaseGet into the FLOW with Extbase
Get into the FLOW with Extbase
 

Similaire à The Hidden Power of HTMLBars (or, Scope in Ember.js Templates)

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
Lecture 3 Perl & FreeBSD administration
Lecture 3 Perl & FreeBSD administrationLecture 3 Perl & FreeBSD administration
Lecture 3 Perl & FreeBSD administration
Mohammed Farrag
 
Working with web_services
Working with web_servicesWorking with web_services
Working with web_services
Lorna Mitchell
 

Similaire à The Hidden Power of HTMLBars (or, Scope in Ember.js Templates) (20)

Redis for the Everyday Developer
Redis for the Everyday DeveloperRedis for the Everyday Developer
Redis for the Everyday Developer
 
Zend Certification Preparation Tutorial
Zend Certification Preparation TutorialZend Certification Preparation Tutorial
Zend Certification Preparation Tutorial
 
One Sass File, So Many Sites
One Sass File, So Many SitesOne Sass File, So Many Sites
One Sass File, So Many Sites
 
Subroutines
SubroutinesSubroutines
Subroutines
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
JSON Schema in Web Frontend #insideFE
JSON Schema in Web Frontend #insideFEJSON Schema in Web Frontend #insideFE
JSON Schema in Web Frontend #insideFE
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Lecture 3 Perl & FreeBSD administration
Lecture 3 Perl & FreeBSD administrationLecture 3 Perl & FreeBSD administration
Lecture 3 Perl & FreeBSD administration
 
Tres Gemas De Ruby
Tres Gemas De RubyTres Gemas De Ruby
Tres Gemas De Ruby
 
Programming in perl style
Programming in perl styleProgramming in perl style
Programming in perl style
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Let's build a parser!
Let's build a parser!Let's build a parser!
Let's build a parser!
 
Cleancode
CleancodeCleancode
Cleancode
 
Redis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your applicationRedis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your application
 
My shell
My shellMy shell
My shell
 
Working with web_services
Working with web_servicesWorking with web_services
Working with web_services
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
Elixir and Dialyzer, Types and Typespecs, using and understanding them
Elixir and Dialyzer, Types and Typespecs, using and understanding themElixir and Dialyzer, Types and Typespecs, using and understanding them
Elixir and Dialyzer, Types and Typespecs, using and understanding them
 
BSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationBSDM with BASH: Command Interpolation
BSDM with BASH: Command Interpolation
 

Plus de Matthew Beale

Scalable vector ember
Scalable vector emberScalable vector ember
Scalable vector ember
Matthew Beale
 

Plus de Matthew Beale (15)

Ember.js Module Loading
Ember.js Module LoadingEmber.js Module Loading
Ember.js Module Loading
 
LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017
 
Interoperable Component Patterns
Interoperable Component PatternsInteroperable Component Patterns
Interoperable Component Patterns
 
Ember Community 2016 - Be the Bark
Ember Community 2016 - Be the BarkEmber Community 2016 - Be the Bark
Ember Community 2016 - Be the Bark
 
Attribute actions
Attribute actionsAttribute actions
Attribute actions
 
Aligning Ember.js with Web Standards
Aligning Ember.js with Web StandardsAligning Ember.js with Web Standards
Aligning Ember.js with Web Standards
 
New Component Patterns in Ember.js
New Component Patterns in Ember.jsNew Component Patterns in Ember.js
New Component Patterns in Ember.js
 
Scalable vector ember
Scalable vector emberScalable vector ember
Scalable vector ember
 
Testing Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyTesting Ember Apps: Managing Dependency
Testing Ember Apps: Managing Dependency
 
Parse Apps with Ember.js
Parse Apps with Ember.jsParse Apps with Ember.js
Parse Apps with Ember.js
 
Snappy Means Happy: Performance in Ember Apps
Snappy Means Happy: Performance in Ember AppsSnappy Means Happy: Performance in Ember Apps
Snappy Means Happy: Performance in Ember Apps
 
Client-side Auth with Ember.js
Client-side Auth with Ember.jsClient-side Auth with Ember.js
Client-side Auth with Ember.js
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
Complex Architectures in Ember
Complex Architectures in EmberComplex Architectures in Ember
Complex Architectures in Ember
 
Ember and containers
Ember and containersEmber and containers
Ember and containers
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Dernier (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

The Hidden Power of HTMLBars (or, Scope in Ember.js Templates)

  • 1. The Hidden Power of HTMLBars or, Scope in Ember.js Templates EmberCamp 2015
  • 16. “Hey, look at those chips”
  • 19. Scope
  • 21. EntityScope + Rules + Label cold beer cold beers
 are served in NYC “chips” thin, flat, and fried
 slices of potato
  • 22. 1 {{! app/templates/components/british-pub.hbs }} 2 <h2>{{name}} Menu</h2> 3 <ul> 4 {{#each snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul>
  • 23. 1 {{! app/templates/components/british-pub.hbs }} 2 <h2>{{name}} Menu</h2> 3 <ul> 4 {{#each snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul> Label
  • 24. 1 {{! app/templates/components/british-pub.hbs }} 2 <h2>{{name}} Menu</h2> 3 <ul> 4 {{#each snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul> Scope
  • 25. Rules
  • 26. 1. Dynamic Scope 2. Lexical (Static) Scope
  • 28. “In languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context or calling context.” Wikipedia
  • 29. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 30. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # local_sub: Fry 6 # show_name: Crisp 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 31. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 32. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 33. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 34. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 35. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 36. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 37. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # local_sub: Fry 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 38. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # local_sub: Fry 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 39. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # local_sub: Fry 6 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 40. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # local_sub: Fry 6 # show_name: Crisp 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 41. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # local_sub: Fry 6 # show_name: Crisp 7 sub local_sub { 8 local $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "local_sub: ", &local_sub(), "n"; 18 print "show_name: ", &show_name(), "n"; What context do you need to understand the value of $name?
  • 42. “In languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context or calling context.” Wikipedia
  • 44. “In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined.” Wikipedia
  • 45. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # my_sub: Crisp 6 # show_name: Crisp 7 sub my_sub { 8 my $name = "Fry"; 9 return show_name(); 10 } 11 12 sub show_name { 13 return $name; 14 } 15 16 print "$name: $namen"; 17 print "my_sub: ", &my_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 46. 1 #!/usr/bin/perl -w 2 use strict; 3 4 our $name; # $name: Crisp 5 $name = "Crisp"; # my_sub: Fry 6 # show_name: Crisp 7 sub my_sub { 8 my $name = "Fry"; 9 return show_name($name); 10 } 11 12 sub show_name { 13 return shift || $name; 14 } 15 16 print "$name: $namen"; 17 print "my_sub: ", &my_sub(), "n"; 18 print "show_name: ", &show_name(), "n";
  • 47. “In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined.” Wikipedia
  • 48. Benefits of Static Scope 1. Possible to optimize at compile time 2. Easier for developers to read 3. JavaScript and pretty much all languages use it
  • 49. 1 {{! app/templates/index.hbs }} 2 <h2>{{name}} Menu</h2> 3 <ul> 4 {{#view 'localized-menu' model}} 5 <li>{{name}}: {{model.price}}</li> 6 {{/view}} 7 </ul> Ember 1.x
  • 50. 1 {{! app/templates/index.hbs }} 2 <h2>{{name}} Menu</h2> 3 <ul> 4 {{#view 'localized-menu' model}} 5 <li>{{name}}: {{model.price}}</li> 6 {{/view}} 7 </ul> Ember 1.x • Index controller • Index controller model • New context from localized-menu • Helper Dynamic
  • 51. 1 {{! app/templates/index.hbs }} 2 <h2>{{name}} Menu</h2> 3 <ul> 4 {{#view 'localized-menu' model}} 5 <li>{{name}}: {{model.price}}</li> 6 {{/view}} 7 </ul> Ember 1.x Ember 2.x 1 {{! app/templates/index.hbs }} 2 <h2>{{model.name}} Menu</h2> 3 <ul> 4 {{#each model.snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul>
  • 52. 1 {{! app/templates/index.hbs }} 2 <h2>{{model.name}} Menu</h2> 3 <ul> 4 {{#each model.snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul> Ember 2.x • Property on packet • Helper Static
  • 53. 1 {{! app/templates/index.hbs }} 2 <h2>{{model.name}} Menu</h2> 3 <ul> 4 {{#each model.snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul> Ember 2.x • Property on packet • Helper Static
  • 54. 1 {{! app/templates/index.hbs }} 2 <h2>{{model.name}} Menu</h2> 3 <ul> 4 {{#each model.snacks as |packet|}} 5 <li>{{packet.name}}: {{packet.price}}</li> 6 {{/each}} 7 </ul> 1 function buildIndex(model) { 2 let html = `<h2>${model.name} Menu</h2>`; 3 html += '<ul>'; 4 model.snacks.forEach(packet => { 5 html += `<li> 6 ${packet.name}: ${packet.price} 7 </li>`; 8 }); 9 html += '</ul>'; 10 return html; 11 } Ember 2.x
  • 55. Creating a template system with static scoping is an intentional goal of HTMLBars/Glimmer, and directs the underlying architecture.
  • 56.
  • 57. Tools for Static Scope Closures
  • 58. Closures 1 function generateSayName() { 2 let name = 'Chips'; 3 return function() { 4 alert(name); 5 }; 6 } 7 8 var sayName = generateSayName(); 9 10 console.log(sayName()); // alerts: Chips
  • 59. 1 function generateSayName() { 2 let name = 'Chips'; 3 return function() { 4 alert(name); 5 }; 6 } 7 8 var sayName = generateSayName(); 9 10 console.log(sayName()); // alerts: Chips Closures
  • 60. Ember Actions as Closures 1 {{#with (action 'alert' name) as |sayName|}} 2 <button {{action sayName}}>Say the name!</button> 3 {{/with}}
  • 61. Ember Actions as Closures 1 {{! app/templates/components/generate-say-name.hbs }} 2 {{yield (action 'alert' name)}} 1 {{! app/templates/index.hbs }} 2 {{#generate-say-name name='Chip' as |sayName|}} 3 <button {{action sayName}}>Say the name!</button> 4 {{/generate-say-name}}
  • 62. Ember Actions as Closures 1 {{! app/templates/components/generate-say-name.hbs }} 2 {{yield (hash 3 sayBritish=(action 'alert' 'Crisp') 4 sayAmerican=(action 'alert' 'Chip') 5 )}} 1 {{! app/templates/index.hbs }} 2 {{#generate-say-name as |ux|}} 3 <button {{action ux.sayBritish}}>Say the name!</button> 4 {{/generate-say-name}}
  • 63. Ember actions are just JavaScript functions.
  • 64. Ember Components as Closures 1 {{! app/templates/index.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{#ux.sayBritish}}Say the name!{{/ux.sayBritish}} 4 {{/generate-say-name}} 1 {{! app/templates/components/generate-say-name.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-name-button' name='Crisp') 4 sayAmerican=(component 'say-name-button' name='Chip') 5 )}}
  • 65. Pods, Local Lookup, and Closures bit.ly/pods-local-lookup speakerdeck.com/rwjblue/a-tale-of-two-pods
  • 66. Pods 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 routes/ 6 index/ 7 template.hbs
  • 67. Pods 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 routes/ 6 index/ 7 template.hbs 1 {{! app/routes/index/template.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}} 4 {{/generate-say-name}}
  • 68. Pods 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 routes/ 6 index/ 7 template.hbs 1 {{! app/routes/index/template.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}} 4 {{/generate-say-name}}
  • 69. 1 {{! app/components/generate-say-name/template.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-name-button' name='Crisp') 4 sayAmerican=(component 'say-name-button' name='Chip') 5 )}} Pods 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 routes/ 6 index/ 7 template.hbs
  • 70. 1 {{! app/components/generate-say-name/template.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-name-button' name='Crisp') 4 sayAmerican=(component 'say-name-button' name='Chip') 5 )}} Pods 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 routes/ 6 index/ 7 template.hbs
  • 71. 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 say-name-button/ 6 template.hbs 7 routes/ 8 index/ 9 template.hbs 1 {{! app/components/generate-say-name/template.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-name-button' name='Crisp') 4 sayAmerican=(component 'say-name-button' name='Chip') 5 )}} Pods
  • 72. 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs 1 {{! app/components/generate-say-name/template.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-name-button' name='Crisp') 4 sayAmerican=(component 'say-name-button' name='Chip') 5 )}} Local Lookup
  • 73. 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs 1 {{! app/components/generate-say-name/template.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-name-button' name='Crisp') 4 sayAmerican=(component 'say-name-button' name='Chip') 5 )}} Local Lookup
  • 74. 1 {{! app/routes/index/template.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}} 4 {{/generate-say-name}} 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs Local Lookup
  • 75. 1 {{! app/routes/index/template.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}} 4 {{/generate-say-name}} 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs Local Lookup
  • 76. 1 {{! .../say-name-button/template.hbs }} 2 <button {{action 'alert' name}}>{{yield}}</button> 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs Local Lookup
  • 77. 1 {{! .../say-name-button/template.hbs }} 2 <button {{action 'alert' name}}>{{yield}}</button> 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs Local Lookup
  • 78. 1 {{! app/routes/index/template.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{#ux.sayBritish}}Say the Name{{/ux.sayBritish}} 4 {{/generate-say-name}} 1 app/ 2 components/ 3 generate-say-name/ 4 template.hbs 5 components/ 6 say-name-button/ 7 template.hbs 8 routes/ 9 index/ 10 template.hbs Local Lookup
  • 80. Tools for Static Scope Partial Applications
  • 81. Partial Application 1 function generateSayName() { 2 let name = 'Chips'; 3 return function(honorific) { 4 alert(`${honorific} ${name}`); 5 }; 6 } 7 8 var sayName = generateSayName(); 9 10 console.log(sayName('Mr.')); // logs: Mr. Chips
  • 82. 1 function generateSayName() { 2 let name = 'Chips'; 3 return function(honorific) { 4 alert(`${honorific} ${name}`); 5 }; 6 } 7 8 var sayName = generateSayName(); 9 10 console.log(sayName('Mr.')); // logs: Mr. Chips Partial Application
  • 83. 1 function generateSayName() { 2 let name = 'Chips'; 3 return function(honorific) { 4 alert(`${honorific} ${name}`); 5 }; 6 } 7 8 var sayName = generateSayName(); 9 10 console.log(sayName('Mr.')); // logs: Mr. Chips Partial Application
  • 84. Ember Actions with Partial Application 1 {{! app/templates/index.hbs }} 2 {{#generate-say-name as |sayName|}} 3 <button {{action sayName 'Mr.'}}>Say the name!</button> 4 {{/generate-say-name}} 1 {{! app/templates/components/generate-say-name.hbs }} 2 {{yield (action 'alert' 'Crisps')}}
  • 85. Ember Actions with Partial Application 1 {{! app/templates/index.hbs }} 2 {{#generate-say-name as |sayName|}} 3 <button {{action sayName 'Mr.'}}>Say the name!</button> 4 {{/generate-say-name}} 1 {{! app/templates/components/generate-say-name.hbs }} 2 {{yield (action 'alert' 'Crisps')}} 1 actions: { 2 alert(name, honorific) { 3 console.log(`${honorific} ${name}`); 4 } 5 }
  • 86. Ember Components with Partial Application 1 {{! app/templates/components/generate-say-name.hbs }} 2 {{yield (hash 3 sayBritish=(component 'say-button-name' honorific='MP') 4 sayAmerican=(component 'say-button-name' honorific='Rep') 5 )}} 1 {{! app/templates/index.hbs }} 2 {{#generate-say-name as |ux|}} 3 {{ux.sayBritish name='Chips'}} 4 {{ux.sayAmerican honorific='Mr.' name='Fry'}} 5 {{/generate-say-name}} 1 {{! app/templates/components/say-button-name.hbs }} 2 <button {{action 'alert' name honorific}}>Say the Name</button>
  • 87. Tools for Static Scope Recursion?! emberjs.jsbin.com/fubutusejo/1/edit?html,js,output
  • 88. Ember templates have the scoping rules and consistency of a real language.
  • 89. Develop using the patterns and tools you would use in a real language.