created a typeahead. neat.

This commit is contained in:
Bryce Covert
2018-05-23 00:30:04 -07:00
parent 37371024d1
commit 1a72859bd8
5 changed files with 138 additions and 20 deletions

View File

@@ -92,6 +92,8 @@
:jar true
:compiler {:main auto-ap.core
:output-to "resources/public/js/compiled/app.js"
:npm-deps {:react-autocomplete "1.8.1"}
:install-deps true
:optimizations :advanced
:closure-defines {goog.DEBUG false}
:pretty-print false}}

View File

@@ -247,6 +247,53 @@
background-color:#F5F5F5;
}
.table { table-layout: fixed }
.typeahead {
position:relative;
}
.typeahead-menu {
position: absolute;
display: inline-block;
width: 100%;
top: 100%;
left: 0;
z-index: 1000;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
font-size: 14px;
text-align: left;
background-color: #ffffff;
border: 1px solid #cccccc;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
background-clip: padding-box;
}
.typeahead-suggestion {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.42857143;
color: #333333;
white-space: nowrap;
}
.typeahead-suggestion:hover,
.typeahead-suggestion:focus,
.typeahead-menu:not(:hover) .typeahead-highlighted
{
color: #ffffff;
text-decoration: none;
outline: 0;
background-color: #00d1b2;
cursor: pointer;
}
</style>

View File

@@ -4,6 +4,7 @@
[auto-ap.subs :as subs]
[auto-ap.routes :as routes]
[auto-ap.effects :as effects]
[auto-ap.utils :refer [by]]
[venia.core :as v]
[bidi.bidi :as bidi]
[goog.crypt.base64 :as b64]
@@ -35,9 +36,11 @@
:user token)
:graphql {:token token
:query-obj {:venia/queries [[:company
[:id :name [:bank-accounts [:id :number :check-number :name]]]]]}
[:id :name [:bank-accounts [:id :number :check-number :name]]]]
[:vendor
[:id :name]]]}
:on-success [::received-companies]}}))))
:on-success [::received-initial]}}))))
(re-frame/reg-event-db
::toggle-menu
@@ -49,19 +52,19 @@
(fn [{:keys [db]} [_ token user]]
{:graphql {:token token
:query-obj {:venia/queries [[:company
[:id :name]]]}
[:id :name [:bank-accounts [:id :number :check-number :name]]]]
[:vendor
[:id :name]]]}
:on-success [::received-companies]}
:on-success [::received-initial]}
:db (assoc db :user (assoc user :token token))}))
(re-frame/reg-event-db
::received-companies
(fn [db [_ {companies :company}]]
(assoc db :companies (reduce (fn [companies company]
(assoc companies (:id company) company))
{}
companies))))
::received-initial
(fn [db [_ {companies :company vendors :vendor :as x}]]
(-> db
(assoc :companies (by :id companies) )
(assoc :vendors (by :id vendors) ))))
(re-frame/reg-event-db
::swap-company

View File

@@ -1,5 +1,7 @@
(ns auto-ap.views.pages.unpaid-invoices
(:require [re-frame.core :as re-frame]
[reagent.core :as r]
[clojure.string :as str]
[auto-ap.entities.companies :as company]
[auto-ap.entities.vendors :as vendor]
[auto-ap.views.utils :refer [dispatch-event bind-field horizontal-field]]
@@ -238,9 +240,60 @@
:max outstanding-balance
:step "0.01"}]]]]]])]]])))
(defn typeahead [{:keys [matches on-change field value]}]
(let [text (r/atom (or (second (first (filter #(= (first %) value) matches))) ""))
highlighted (r/atom 0)
selected (r/atom (first (first (filter #(= (first %) value) matches))))
select (fn [[id t]]
(reset! selected id)
(reset! text t)
(println [id t])
(when on-change
(on-change id)))]
(fn [{:keys [matches on-change field value]}]
(let [valid-matches (take 5 (for [[[id t :as match] i] (map vector matches (range))
:when (str/includes? (.toLowerCase t) (.toLowerCase @text))]
match))]
[:div.typeahead
[:input.input {:type "text"
:field [:vendor]
:value @text
:on-blur (fn [e]
(cond @selected
nil
(seq valid-matches)
(do (select (first valid-matches))
true)
:else
(do (select [nil ""])
true))
)
:on-key-up (fn [e]
(if (= 13 (.-keyCode e))
(do
(select (first valid-matches))
false)
true))
:on-change (fn [e]
(reset! highlighted (ffirst valid-matches))
(select [nil (.. e -target -value)]))}]
(when (and (seq @text)
(not @selected)
(seq valid-matches))
[:div.typeahead-menu
[:ul
(for [[id t :as match] valid-matches]
[:li.typeahead-suggestion {:class (if (= id @highlighted)
"typeahead-highlighted")
:on-mouse-down #(do (println "MATCH" match) (select match))} t])]])]))))
(defn new-invoice-modal []
(let [data @(re-frame/subscribe [::new-invoice])
change-event [::events/change-form [::new-invoice]]]
(println data)
[action-modal {:id ::new-invoice
:title "New Invoice"
:action-text "Create"
@@ -248,10 +301,11 @@
[horizontal-field
[:label.label "Vendor"]
[bind-field
[:input.input {:type "text"
:field [:vendor]
:event change-event
:subscription data}]]]
[typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/vendors]))
:type "typeahead"
:field [:vendor-id]
:event change-event
:subscription data}]]]
[horizontal-field
[:label.label "Date"]
[bind-field
@@ -263,10 +317,11 @@
[horizontal-field
[:label.label "Company"]
[bind-field
[:input.input {:type "text"
:field [:company]
:event change-event
:subscription data}]]]
[typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/companies]))
:type "typeahead"
:field [:company-id]
:event change-event
:subscription data}]]]
[horizontal-field
[:label.label "Invoice #"]

View File

@@ -68,11 +68,22 @@
keys (dissoc keys :field :subscription :event :spec)]
(into [dom keys] (with-keys rest))))
(defmethod do-bind "typeahead" [dom {:keys [field event subscription class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
:on-change (fn [selected]
(re-frame/dispatch (conj (conj event field) selected)))
:value (get-in subscription field)
:class (str class
(when (and spec (not (s/valid? spec (get-in subscription field))))
" is-danger")))
keys (dissoc keys :field :subscription :event :spec)]
(into [dom keys] (with-keys rest))))
(defmethod do-bind :default [dom {:keys [field event subscription class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
_ (println field event dom rest)
keys (assoc keys
:on-change (dispatch-value-change (conj event field))
:value (get-in subscription field)