Skip to content

Instantly share code, notes, and snippets.

@visualjeff
Last active July 30, 2016 22:24
Show Gist options
  • Save visualjeff/8c04d19680293fdb2af7c69023022563 to your computer and use it in GitHub Desktop.
Save visualjeff/8c04d19680293fdb2af7c69023022563 to your computer and use it in GitHub Desktop.
Ember Component Learnings
Ember Component Learnings:
==========================
Don't ever assign a dynamic value to a id or name attribute of a field
Don't share state between components. Always reset or init properties via the init method. Same for mixins.
Warning:
========
Because components are sealed from outside events. It challenging to
get them to refresh on command. To pull this off you essentially need
them to observe a property on a controller in order to get them to refresh.
Property changes, component refreshes.
Ember component notes from ember conf 2016
==========================================
REMINDER or WARNING:
Don't share state between components. Always reset or init properties via the init method. Same holds true for mixins.
Composable Component notes:
---------------------------
Avoid muting state in child components. The parent should be the owner. Let the child send an action up to the parent.
NOTE: Services can also own their own data. Singleton need to be moved into services because routable components will be stateless. Routable components will replace controllers. They will still decorate the data associated with the template. Implementation will change.
To future proof against this change:
-Move route level templates into a top level component.
-In the future, components invocation to the route
-Move statefull bits to service
-Move stateless bits to component
Actions:
--------
Classic (string) vs New-style or closure actions (Really just a Javascript function).
NOTE: Classic actions force you to use sendAction in your components. This can be hard to debug. Nothing is returned.
New style actions look like:
get(this, 'submit')(...args);
The benefit to new style is you now have return values! Helpful with Asynchronsis actions.
get(this, 'save')(item).then((savedItem) => // do stuff);
NOTE: New style actions defined on the controller DO NOT bubble up.
ember install ember-route-action-helper
Uses "route-action" to facilitate move new style actions to the route.
Services:
---------
For long lived singleton state.
Computed properties:
--------------------
Suggestion to use rwj's computed annotation. Might be helpful.
Why use them compouted properties:
1. Business logic
2. Reusable
3. Change is implicit (sometimes hard to understand why something changed)
Computed properties can also be used in the model.
Helpers:
--------
Easy to implement your own. Examples include repeat or capitalize.
Why use them:
1. Express UI logic
2. Composable
3. Simple mental model
4. Can be used as an action
5. No hooks available. Yet.
Examples:
add, component, concat, dasherize, eq, pipe
To get pipe or dasherize:
ember install ember-composable-helpers
FYI: The {{component}} helper expects the component name as the second parameter, and will dynamically render out the component by that name. An arbitrary number of parameters may follow the component name.
{{component myComponentName param1=param1 param2=param2 ...}}
For example:
// food/component.js
import Ember from 'ember';
const { Component, computed, get } = Ember;
export default Component.extend({
tastyComponentName: computed('food.taste', {
get() {
let foodTaste = get(this, 'food.taste');
return `food/${foodTaste}-food`;
}
})
});
{{! food/template.hbs }}
{{component tastyComponentName food=food}}
We can forgo the CP altogether and use Handlebars subexpressions to keep all logic within the template.
The Ember helper concat is one of the helpers we use fairly often. It's common to name components based on a value of an attribute.
{{! food/template.hbs }}
{{component (concat "food/" food.taste "-food") food=food}}
The concat helper replaces the computed property entirely. If the value of food.taste is sweet, then the helper will output food/sweet-food. Sometimes, we have to work with camelized values, and using dasherize will convert them to a more desired format. In this case, if the value of food.taste is SuperSour, then our rendered component will be food/super-sour-food.
{{component (concat "food/" (dasherize food.taste) "-food") food=food}}
Components:
-----------
Component hooks:
NOTE: Don't ever use didRender hook to update attrs unless you like infinite loops.
Hooks include:
initial Render External attr changed Internal value changed
-------------- --------------------- ----------------------
init didUpdateAttrs
didReceiveAttrs didReceiveAttrs
willRender willUpdate willUpdate
didInsertElement didUpdate didUpdate
didRender didRender didRender
On initial render you should use init and didInsertElement.
On external attr changed you should use didUpdate.
On internal value change you should use didUpdate.
Observers?
----------
Don't use them!
ember process is like game processing:
1. application state Ember ==> 2. HTMLBars ==> 3. Glimmer
||
4. Dom API's
||
5. Browser
||
6. Screen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment