Last active
August 29, 2015 14:16
-
-
Save arnaudbos/8f4d53020d941af5a5cb to your computer and use it in GitHub Desktop.
should-component-update with vector
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns todomvc | |
| (:require [reagent.core :as reagent :refer [atom]])) | |
| (defonce todos (atom (sorted-map))) | |
| (defonce counter (atom 0)) | |
| (defn add-todo [text] | |
| (let [id (swap! counter inc)] | |
| (swap! todos assoc id {:id id :title text :done false}))) | |
| (defn toggle [id] (swap! todos update-in [id :done] not)) | |
| (defn save [id title] (swap! todos assoc-in [id :title] title)) | |
| (defn delete [id] (swap! todos dissoc id)) | |
| (defn mmap [m f a] (->> m (f a) (into (empty m)))) | |
| (defn complete-all [v] (swap! todos mmap map #(assoc-in % [1 :done] v))) | |
| (defn clear-done [] (swap! todos mmap remove #(get-in % [1 :done]))) | |
| (defonce init (do | |
| (add-todo "Rename Cloact to Reagent") | |
| (add-todo "Add undo demo") | |
| (add-todo "Make all rendering async") | |
| (add-todo "Allow any arguments to component functions") | |
| (complete-all true))) | |
| (defn todo-input [{:keys [title on-save on-stop]}] | |
| (let [val (atom title) | |
| stop #(do (reset! val "") | |
| (if on-stop (on-stop))) | |
| save #(let [v (-> @val str clojure.string/trim)] | |
| (if-not (empty? v) (on-save v)) | |
| (stop))] | |
| (fn [props] | |
| [:input (merge props | |
| {:type "text" :value @val :on-blur save | |
| :on-change #(reset! val (-> % .-target .-value)) | |
| :on-key-down #(case (.-which %) | |
| 13 (save) | |
| 27 (stop) | |
| nil)})]))) | |
| (def todo-edit (with-meta todo-input | |
| {:component-did-mount #(.focus (reagent/dom-node %))})) | |
| (defn todo-stats [{:keys [filt active done]}] | |
| (let [props-for (fn [name] | |
| {:class (if (= name @filt) "selected") | |
| :on-click #(reset! filt name)})] | |
| [:div | |
| [:span#todo-count | |
| [:strong active] " " (case active 1 "item" "items") " left"] | |
| [:ul#filters | |
| [:li [:a (props-for :all) "All"]] | |
| [:li [:a (props-for :active) "Active"]] | |
| [:li [:a (props-for :done) "Completed"]]] | |
| (when (pos? done) | |
| [:button#clear-completed {:on-click clear-done} | |
| "Clear completed " done])])) | |
| (defn -todo-item [] | |
| (let [editing (atom false)] | |
| (fn [{:keys [id done title]}] | |
| (.log js/console "todo-item rendering") | |
| (.log js/console (str id " " done " " title)) | |
| [:li {:class (str (if done "completed ") | |
| (if @editing "editing"))} | |
| [:div.view | |
| [:input.toggle {:type "checkbox" :checked done | |
| :on-change #(toggle id)}] | |
| [:label {:on-double-click #(reset! editing true)} title] | |
| [:button.destroy {:on-click #(delete id)}]] | |
| (when @editing | |
| [todo-edit {:class "edit" :title title | |
| :on-save #(save id %) | |
| :on-stop #(reset! editing false)}])]))) | |
| (def todo-item | |
| (with-meta -todo-item | |
| { | |
| :component-will-mount (fn [this] | |
| (.log js/console "-todo-item will-mount") | |
| ) | |
| :component-did-mount (fn [this] | |
| (.log js/console "-todo-item did-mount") | |
| ) | |
| :component-will-update (fn [this] | |
| (.log js/console "-todo-item will-update") | |
| ) | |
| :component-did-update (fn [this] | |
| (.log js/console "-todo-item did-update") | |
| ) | |
| :component-will-unmount (fn [this] | |
| (.log js/console "-todo-item will-unmount") | |
| ) | |
| :should-component-update (fn [this old-argv new-argv] | |
| (not= old-argv new-argv)) | |
| })) | |
| (defn -todo-app [props] | |
| (let [filt (atom :all)] | |
| (fn [] | |
| (.log js/console "todo-app rendering") | |
| (let [items (vals @todos) | |
| done (->> items (filter :done) count) | |
| active (- (count items) done)] | |
| [:div | |
| [:section#todoapp | |
| [:header#header | |
| [:h1 "todos"] | |
| [todo-input {:id "new-todo" | |
| :placeholder "What needs to be done?" | |
| :on-save add-todo}]] | |
| (when (-> items count pos?) | |
| [:div | |
| [:section#main | |
| [:input#toggle-all {:type "checkbox" :checked (zero? active) | |
| :on-change #(complete-all (pos? active))}] | |
| [:label {:for "toggle-all"} "Mark all as complete"] | |
| [:ul#todo-list | |
| (comment for [todo (filter (case @filt | |
| :active (complement :done) | |
| :done :done | |
| :all identity) items)] | |
| ^{:key (:id todo)} [todo-item todo]) | |
| (map-indexed | |
| (fn [i todo] | |
| ^{:key (:id todo)} [todo-item (assoc todo :path [i])]) | |
| (filter (case @filt | |
| :active (complement :done) | |
| :done :done | |
| :all identity) items)) | |
| ]] | |
| [:footer#footer | |
| [todo-stats {:active active :done done :filt filt}]]])] | |
| [:footer#info | |
| [:p "Double-click to edit a todo"]]])))) | |
| (def todo-app | |
| (with-meta -todo-app | |
| { | |
| :component-will-mount (fn [this] | |
| (.log js/console "-todo-app will-mount") | |
| ) | |
| :component-did-mount (fn [this] | |
| (.log js/console "-todo-app did-mount") | |
| ) | |
| :component-will-update (fn [this] | |
| (.log js/console "-todo-app will-update") | |
| ) | |
| :component-did-update (fn [this] | |
| (.log js/console "-todo-app did-udpate") | |
| ) | |
| :component-will-unmount (fn [this] | |
| (.log js/console "-todo-app will-unmount") | |
| ) | |
| })) | |
| (defn ^:export run [] | |
| (reagent/render [todo-app] | |
| (js/document.getElementById "app"))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment