Skip to content

Instantly share code, notes, and snippets.

@givanse
Last active February 27, 2017 20:55
Show Gist options
  • Save givanse/c94d165be632ce921104f0242474ecf5 to your computer and use it in GitHub Desktop.
Save givanse/c94d165be632ce921104f0242474ecf5 to your computer and use it in GitHub Desktop.
composing with ember components
import Ember from 'ember';
export default Ember.Component.extend({
classNames: ['dialogue-body']
});
import Ember from 'ember';
let component = Ember.Component.extend({
classNames: ['text-right']
});
component.reopenClass({
positionalParams: ['label']
});
export default component;
import Ember from 'ember';
let component = Ember.Component.extend({
tagName: 'section',
classNames: ['dialogue-box']
});
component.reopenClass({
positionalParams: ['title', 'message']
});
export default component;
import Ember from 'ember';
let component = Ember.Component.extend({
tagName: 'section',
classNames: ['dialogue-box']
});
component.reopenClass({
positionalParams: ['title']
});
export default component;
import Ember from 'ember';
let component = Ember.Component.extend({
tagName: 'section',
classNames: ['dialogue-box']
});
component.reopenClass({
positionalParams: ['title']
});
export default component;
import Ember from 'ember';
export default Ember.Controller.extend({
});
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: 'none',
rootURL: config.rootURL
});
Router.map(function() {
this.route('passing-properties');
this.route('block-form');
this.route('contextual-components');
});
export default Router;
import Ember from 'ember';
export default Ember.Route.extend({
});
import Ember from 'ember';
export default Ember.Route.extend({
});
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.dialogue-box {
border: 1px solid gray;
border-radius: 4px;
padding: 4px 8px;
background-color: #ffffd4;
}
.dialogue-body {
border: 1px solid gray;
border-radius: 4px;
padding: 4px 8px;
background-color: #ffffd4;
}
.mono {
font-family: monospace;
}
.text-right {
text-align: right;
}
button {
font-size: 1.5rem;
margin: 4px;
border-radius: 4px;
}
<h1>composing with components</h1>
<header>
<ol>
<li>
{{link-to 'Passing Properties' 'passing-properties'}}
</li>
<li>
{{link-to 'Block Form' 'block-form'}}
</li>
<li>
{{link-to 'Contextual Components' 'contextual-components'}}
</li>
</ol>
</header>
{{outlet}}
<br>
<br>
<h2>Block form</h2>
<pre>
\{{#v2-dialogue-box "v2 dialogue"}}
Lorem ipsum dolor sit amet.
\{{/v2-dialogue-box}}
</pre>
{{#v2-dialogue-box "v2 dialogue"}}
Lorem ipsum dolor sit amet.
{{/v2-dialogue-box}}
<p>
It's important to note that the template scope inside the component block is the same as outside.
</p>
<p>
Using the block form solves for easy CSS customization, but not for sharing data privately.
</p>
<h3>{{attrs.title}}</h3>
<hr>
{{#dialogue-body}}
<p>
{{attrs.message}}
</p>
{{/dialogue-body}}
{{ok-button "ok"}}
<h3>{{attrs.title}}</h3>
<hr>
{{#dialogue-body}}
{{yield}}
{{/dialogue-body}}
{{ok-button "ok"}}
<h3>{{attrs.title}}</h3>
<hr>
{{yield (hash
body=(component "dialogue-body")
button=(component "ok-button" "ok")
)}}
<h2>Contextual Components</h2>
<i>available since <a href="http://emberjs.com/blog/2016/01/15/ember-2-3-released.html#toc_contextual-components">Ember 2.3.0-beta.1</a>, <a href="https://github.com/emberjs/rfcs/blob/master/text/0064-contextual-component-lookup.md">RFC 0064</a></i>
<pre>
\{{#v3-dialogue-box "v3 dialogue" as |dialogue|}}
\{{dialogue.button "okay"}}
\{{#dialogue.body}}
&lt;p class="mono">
My very special message.
&lt;/p>
\{{/dialogue.body}}
P.D. xoxox
\{{/v3-dialogue-box}}
</pre>
{{#v3-dialogue-box "v3 dialogue" as |dialogue|}}
{{dialogue.button "okay"}}
{{#dialogue.body}}
<p class="mono">
My very special message.
</p>
{{/dialogue.body}}
P.D. xoxox
{{/v3-dialogue-box}}
<p>
Now we've been able to customize the label of the ok-button without having to pass the data through the parent component. We kept the data private to the template (scope) that renders it.
</p>
<h2>Passing Properties</h2>
<pre>
\{{v1-dialogue-box "v1 dialogue" "Lorem ipsum dolor sit amet."}}
</pre>
{{v1-dialogue-box
"v1 dialogue"
"Lorem ipsum dolor sit amet."}}
<p>
If we wanted to customize the style of the dialogue body we would have to define style rules for the CSS query:
</p>
<pre>.dialogue-body > p</pre>
<p>Too generic, can be the source of a bug.</p>
<p>
The next option is to add a specific CSS class to the `p` tag. However, any consumer of this component would have to load and then override that CSS if some customization was needed.
</p>
{
"version": "0.10.4",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.7.0",
"ember-data": "2.7.0",
"ember-template-compiler": "2.7.0"
},
"addons": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment