Reactivity in User Interfaces
"the principle that any changes to application state are reflected immediately to the user, visually or otherwise."
Charles Lowell, Reactive Modeling with Ember
Changes in Application State Reflected Visually
Most Direct Example, A Spreadsheet
Two Static Properties (A,B) and a Visualized Dyamic Relationship
A more complex example, Color Wheel
Adobe Color CC
This principle of instant feedback is what makes reactive interfaces... so low friction because the consequences of any action are immediately understood. This encourages the user to experiment and probe the relationships between the data in your application. They can “play” in order to verify or invalidate hypotheses.
Charles Lowell, Reactive Modeling with Ember
Given Static Inputs
Visualize Dynamic Relationships
So users can play with data
—Techniques—
Techniques
- Reactive Primitives
- Reactive Primitives in Ember
- Ember.Model
- Ember.computed
Reactive Primitives
What we're looking for
- Observable(so we can react to changes)
- Support Dynamic Relationships(between static inputs)
- Run Loop(to set everything in motion)
Reactive Primitives In Ember
- Observable -> Ember.Object
- Reactive -> Ember.computed
- Run Loop -> Ember's Runloop (via Backburner.js)
Reach Goals
For the reactive part
Lazy Evaluation ( So we are not crunching data before we need it )
Composeable ( Keep relationships can reusable and lego-ish )
Testable ( Clean encapsulated pieces we can test)
Easy to Reason About
Primitive #1
Observable: Ember.Object
Ember.Object, Setter/Getter
// Setter and Getter Required for Observation
const human = Ember.Object.create({});
human.set('name', 'bob');
human.get('name'); // => "name"
Ember.Object, Observable Example
// app/application/route
import Ember from 'ember';
const Human = Ember.Object.extend();
export default Ember.Route.extend({
model() {
return Human.create({ firstName: 'bob' });
}
});
{{! app/templates/application.hbs }}
Why, hello there {{model.firstName}}!<br>
<p>
First Name:
{{input value=model.firstName}}
</p>
Ember.Object Running Example
Primitive #2
Reactive: Ember.computed
- Treat a function like a property
- Define dependent keys
- Re-evaluate property if dependent key changes
Ember.Object, Computed Property Example
import Ember from 'ember';
const { computed } = Ember;
const Human = Ember.Object.extend({
fullName: computed( 'firstName', 'lastName', function() {
return `${this.get('firstName')} ${this.get('lastName')}`;
})
});
export default Ember.Route.extend({
model() {
return Human.create({ firstName: 'bob', lastName: 'smith' });
}
});
Why, hello there {{model.fullName}}!<br>
<p>
First Name:
{{input value=model.firstName}}
</p>
<p>
<label>Last Name:</label>
{{input value=model.lastName}}
</p>
Ember.computed Running Example
Computed Properties: Marcos
Forming more complex reactive relationships
import Ember from 'ember';
import EmberCPM from 'ember-cpm';
const { Macros: { sum, difference, product }} = EmberCPM;
export default Ember.Component.extend({
num1: 45,
num2: 3.5,
num3: 13.4,
num4: -2,
total: sum(
sum('num1', 'num2', 'num3'),
difference('num3', 'num2'),
product(difference('num2', 'num1'), 'num4')
)
});
Computed Properties: Best Practices
With great power...
- Keep your functions pure(Avoid side effects at all costs)
- Treat dependent keys like parameters(If you use it, declare it)
- Uni-directional data flow is easier(make data relationshiops more direct and easier to think about)
- Dynamic Values should Decorate Static Values(or at least that's how I like to think about it)
We'll start with a human problem
I'm tired of figuring out how much to eat.
Harris Benedict Equation is a formula that uses your BMR and then applies an activity factor to determine your total daily energy expenditure (calories)
Activivty Level
Formula
none
= BMR x 1.2
light
= BMR x 1.375
moderate
= BMR x 1.55
intense
= BMR x 1.725
ultra brutal
= BMR x 1.9
http://www.bmi-calculator.net/bmr-calculator/harris-benedict-equation/
The BMR formula uses the variables of height, weight, age and gender to calculate the Basal Metabolic Rate (BMR)
Women:
BMR = 655 + ( 4.35 x weight, lbs ) + ( 4.7 x height, inches ) - ( 4.7 x age, years )
Men:
BMR = 66 + ( 6.23 x weight, lbs) + ( 12.7 x height, inches ) - ( 6.8 x age, year )
http://www.bmi-calculator.net/bmr-calculator/bmr-formula.php
Human Inputs
Need to Determine
How much to eat based on amount of activity
Create our Human, and Load as Model
Build _VERY_ basic interface
Compose all the things to setup BMR
Reacting to Change
Responsibly ...with javascript
Created by Ryan LaBouve / @ryanlabouve