Angular to Reagent

Learning the difference between Simple and Easy

NowThis

  • Video news for Millennials
  • Distributed via social networks
  • 950m views in Dec 2015

Me

  • Nate Wildermuth
  • Army Ranger, Teacher
  • LAMP CMS
  • Lead FE CLJS

Agenda

  • Our Application
  • Our Problem
  • Our Solution

NowThis Admin

(CMS + Analytics)

Harbingers of Complexity

"This application will self-destruct in 10, 9, 8, 7 . . ."

Your SPA has more than a single page

SEGMENTATION != SIMPLICITY

Your files grow bigger and bigger

ORGANIZATION != SIMPLICITY

Your application won't f***ing work

Did you try turning it off and on?

Did you try refreshing your browser?

Am I a bad...?

  • "engineer"
  • developer
  • thinker
  • human being

Is my toolkit an engine of complexity?

Engine of Complexity

Simple or Complex?

I do know. I want to know.

Feature-freeze

Decomplecting

  • HTML
  • Controllers
  • Services
  • Directives

HTML

<div class="page">
  <h2>This is markup</h2>
  <p class="content">I do two things</p>
</div>
(def page :div.page)
(def header :h2)
(def content :p.content)

[page
  [header "This is data"]
  [content "I do one thing"]]

HTML

Data

  • Data
  • Markup
  • Data
  • Markup

Easy or Simple?

Harder?

Controllers

(DOM Events)

$scope.say = function(name) {
  console.log("Hi, " + name);
}

<div ng-click="say('Nate')">Say hi.</div>

callbacks

Easy or Simple?

(def click-ch (chan)

(defn div-click [name]
  (put! click-ch name))

[:div {:on-click #(div-click "Nate")} 
      "Say hi!"]'

;; Handle clicks somewhere else

channels

  • Trigger Event
  • Handle Event
  • Trigger Event
  • Handle Event

Harder?

Controllers

(DOM Rendering)

$scope.myFavorite = "soylent";
$scope.foods = ["tacos", 
                "shrimp", 
                "soylent"];

<select ng-model="myFavorite">
  <option ng-repeat="food in foods" 
          value="{{food}}">
    {{food}}
  </option>
</select>
(def my-favorite :soylent)
(def foods [:tacos :shrimp :soylent])

(defn select-options [options]
  (for [option options]
     [:option {:value option} option]

(defn select-favorite [favorite foods]
  (let [options (select-options foods)
        attrs {:value favorite}]
    [:select attrs options]))

two-way binding

pure functions

Easy or Simple?

  • Render Data
  • Update Data
  • Render Data
  • Update Data

Harder?

Services

(Data modeling)

(def users (atom []))

(defn get-users []
  (deref users))

(defn add-user [user]
  (swap! users conj user])

mutability

immutability

  • Data storage
  • Data API
  • Data storage
  • Data API

Easy or Simple?

Harder?

Users.get(function(users) {
  $scope.users = users; // Copy
}

$scope.addUser = function(user) {
  Users.add(user, function(users) {
    $scope.users = users; // Updated Copy
  });
}
Users.get(function(users) {
  $scope.users = users; // Reference
}

$scope.addUser = function(user) {
  $scope.users.push(user); // Triple-binding!!!
}

Services

(State management)

(defn add-user [users user]
  (conj users user))

objects

functions

  • Update state
  • Store state
  • Update state
  • Store state

Easy or Simple?

Harder?

return {
  users: [],
  addUser: function (user, cb) {
    this.users.push(user);
    cb(this);
  }
};

Directives

(template + controller + service)

Good Riddance

The Hard Part

(live coding)

Angular Reagent
Templates Data & Functions
Controllers Channels & Functions
Services Atoms & Functions
Directives Reagent Components

Angular to CLJS

By wildermuthn

Angular to CLJS

  • 638