Skip to content

Commit 58cf597

Browse files
committed
Manual angular components
Resolves issue #2 by requiring that the annotation and writing-up of angular components is done manually. This can be done through the foreign function interface, or in a companion javascript file.
1 parent 5510335 commit 58cf597

21 files changed

+606
-840
lines changed

bower.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
"dist"
1818
],
1919
"dependencies": {
20-
"purescript-maybe": "0.1.3"
20+
"purescript-maybe": "0.2.0"
2121
},
2222
"devDependencies": {
23-
"angular": "1.2.20",
23+
"angular": "1.2.22",
2424
"todomvc-common": "0.1.9",
2525
"purescript-strings": "0.2.1",
26-
"purescript-arrays": "0.1.8",
27-
"purescript-control": "0.1.1",
26+
"purescript-arrays": "0.2.0",
27+
"purescript-control": "0.2.0",
2828
"purescript-foldable-traversable": "0.1.3"
2929
}
3030
}

examples/Todomvc/Controller.purs

Lines changed: 59 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,50 @@
1-
module Todomvc.Controller where
1+
module Todomvc.Controller (todoctrl) where
22

33
import qualified Data.Array as A
44
import qualified Data.String as S
55
import Data.Foldable
66
import Data.Maybe
77
import Control.Monad (unless, when)
88
import Control.Monad.Eff
9-
import Control.Monad.ST (ST(..), STArray(..), newSTArray, runSTArray)
9+
import Control.Monad.ST (ST(), STArray(), newSTArray, runSTArray)
1010

1111
import Angular (copy, extend)
12-
import Angular.Controller (ReadScopeState(..), WriteScopeState(..), controller, readScopeState, writeScopeState, modifyScopeState)
13-
import Angular.Location (location, getPath, setPath)
14-
import Angular.Scope (Scope(..), watch)
12+
import Angular.Location (Location(), getPath, setPath)
13+
import Angular.Scope (Scope(), watch, readScope, extendScope, modifyScope)
14+
import Angular.This(readThis, writeThis)
1515
import Angular.ST (readSTArray, pushSTArray, pushAllSTArray, writeSTArray, spliceSTArray)
1616

17-
import Todomvc.Storage (Store(..), Todo(..), get, put)
17+
import Todomvc.Storage (Store(), Todo(), get, put)
1818

1919
addTodo scope = do
20-
s <- readScopeState scope
20+
s <- readScope scope
2121
let title = S.trim s.newTodo
2222
let empty = (S.length title) == 0
2323
unless empty $ do
2424
let todo = { title: title, completed: false }
2525
todos <- get
2626
put $ todos <> [todo]
2727
pushSTArray s.todos todo
28-
writeScopeState { newTodo: "" , remainingCount: s.remainingCount + 1 } scope
29-
return unit
28+
extendScope { newTodo: ""
29+
, remainingCount: s.remainingCount + 1 } scope
3030

3131
todoCompleted scope todo
32-
= modifyScopeState (\s -> do
32+
= modifyScope (\s -> do
3333
let change = if todo.completed then -1 else 1
3434
arr <- readSTArray s.todos
3535
put arr
3636
return { remainingCount: s.remainingCount + change }
3737
) scope
3838

3939
clearCompletedTodos scope = do
40-
s <- readScopeState scope
40+
s <- readScope scope
4141
arr <- readSTArray s.todos
4242
let res = A.filter (\a -> not a.completed) arr
4343
put res
4444
writeSTArray s.todos res
4545

4646
markAll scope compl
47-
= modifyScopeState (\s -> do
47+
= modifyScope (\s -> do
4848
arr <- readSTArray s.todos
4949
let res = (\a -> a { completed = not compl }) <$> arr
5050
put res
@@ -54,10 +54,11 @@ markAll scope compl
5454

5555
editTodo scope todo = do
5656
cp <- copy todo
57-
writeScopeState { editedTodo: Just todo , originalTodo: Just $ cp } scope
57+
extendScope { editedTodo: Just todo
58+
, originalTodo: Just $ cp } scope
5859

5960
doneEditing scope todo
60-
= modifyScopeState (\s -> do
61+
= modifyScope (\s -> do
6162
let title = S.trim todo.title
6263
when (S.length title == 0) $ removeTodo scope todo
6364
extend todo { title: title }
@@ -67,17 +68,17 @@ doneEditing scope todo
6768
) scope
6869

6970
removeTodo scope todo = do
70-
s <- readScopeState scope
71+
s <- readScope scope
7172
arr <- readSTArray s.todos
7273
let i = A.findIndex (\a -> refEq a todo) arr
7374
unless (i == -1) do
7475
let c = if todo.completed then 0 else -1
75-
writeScopeState { remainingCount: s.remainingCount + c} scope
76+
extendScope { remainingCount: s.remainingCount + c} scope
7677
spliceSTArray s.todos i 1 []
7778
put arr
7879

7980
revertEditing scope todo = do
80-
s <- readScopeState scope
81+
s <- readScope scope
8182
arr <- readSTArray s.todos
8283
let i = A.findIndex (\a -> refEq a todo) arr
8384
unless (i == -1) do
@@ -88,40 +89,46 @@ revertEditing scope todo = do
8889
return unit
8990
Nothing -> return unit
9091

91-
watchRemainingCount scope = do
92-
watch "remainingCount == 0" (Just (\a1 _ _ ->
93-
writeScopeState { allChecked: a1 } scope >>= (\_ -> return unit))) false scope
92+
watchRemainingCount scope =
93+
let expr = "remainingCount == 0"
94+
listener = \a _ _ -> extendScope { allChecked: a } scope
95+
in watch expr (return listener) false scope
9496

95-
watchLocationPath scope = do
96-
watch "location.path()" (Just (\a1 _ _ ->
97-
case a1 of
98-
"/completed" -> writeScopeState { statusFilter: {completed: true} } scope >>= (\_ -> return unit)
99-
"/active" -> writeScopeState { statusFilter: {completed: false} } scope >>= (\_ -> return unit)
100-
_ -> writeScopeState { statusFilter: {} } scope >>= (\_ -> return unit)
101-
)) false scope
97+
watchLocationPath scope =
98+
let expr = "location.path()"
99+
listener = \a _ _ -> case a of
100+
"/completed" -> extendScope { statusFilter: { completed: true } } scope
101+
"/active" -> extendScope { statusFilter: { completed: false } } scope
102+
_ -> extendScope { statusFilter: { } } scope
103+
in watch expr (return listener) false scope
102104

103-
todoController m =
104-
controller "TodoCtrl" m $ \scope _ -> do
105-
loc <- location
106-
path <- getPath loc
107-
if S.length path == 0 then setPath "/" loc else return ""
108-
watchRemainingCount scope
109-
watchLocationPath scope
110-
todosRef <- newSTArray 0 { title: "", completed: false }
111-
todos <- get
112-
pushAllSTArray todosRef todos
113-
let remainingCount = foldl (\b a -> if a.completed then b else b + 1) 0 todos
114-
writeScopeState { newTodo: ""
115-
, editedTodo: Nothing
116-
, originalTodo: Nothing
117-
, todos: todosRef
118-
, remainingCount: remainingCount
119-
, location: loc
120-
, addTodo: addTodo scope
121-
, todoCompleted: todoCompleted scope
122-
, clearCompletedTodos: clearCompletedTodos scope
123-
, markAll: markAll scope
124-
, editTodo: editTodo scope
125-
, doneEditing: doneEditing scope
126-
, removeTodo: removeTodo scope
127-
, revertEditing: revertEditing scope } scope
105+
controller scope location = do
106+
path <- getPath location
107+
if S.length path == 0 then setPath "/" location else return ""
108+
watchRemainingCount scope
109+
watchLocationPath scope
110+
todosRef <- newSTArray 0 { title: "", completed: false }
111+
todos <- get
112+
pushAllSTArray todosRef todos
113+
let remainingCount = foldl (\b a -> if a.completed then b else b + 1) 0 todos
114+
extendScope { newTodo: ""
115+
, editedTodo: Nothing
116+
, originalTodo: Nothing
117+
, todos: todosRef
118+
, remainingCount: remainingCount
119+
, location: location
120+
, addTodo: addTodo scope
121+
, todoCompleted: todoCompleted scope
122+
, clearCompletedTodos: clearCompletedTodos scope
123+
, markAll: markAll scope
124+
, editTodo: editTodo scope
125+
, doneEditing: doneEditing scope
126+
, removeTodo: removeTodo scope
127+
, revertEditing: revertEditing scope } scope
128+
129+
foreign import todoctrl
130+
" /*@ngInject*/function todoctrl($scope, $location) { \
131+
\ var impl = controller($scope)($location); \
132+
\ return impl.apply(this, []); \
133+
\ } "
134+
:: forall e a. Scope a -> Location -> Eff e Unit

examples/Todomvc/Escape.purs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
module Todomvc.Escape where
1+
module Todomvc.Escape (EscapeDirective(), escape) where
22

33
import Data.Maybe
44

55
import Angular.Attributes (get)
6-
import Angular.Directive (LinkFn(..), directive, defn, postLink)
76
import Angular.Element (El(..), on)
87
import Angular.Scope (apply, stringApplyExpr)
98

9+
foreign import data EscapeDirective :: *
10+
1011
escapeKey = 27
1112

12-
escapeLink :: forall e a b c d. LinkFn (ngel :: El | e) a b c d
13-
escapeLink scope element attrs ctrls trans = do
13+
link scope element attrs = do
1414
on "keydown" (\e -> if e.keyCode == escapeKey
1515
then (get attrs) >>= (\as -> apply (stringApplyExpr as.todoEscape) scope)
1616
else return unit) element
17-
return unit
1817

19-
escapeDirective m =
20-
directive "todoEscape" m $ return defn { link = postLink escapeLink }
18+
foreign import escape
19+
" /*@ngInject*/function escape(){ \
20+
\ return { \
21+
\ link: function($scope, $element, $attrs){ \
22+
\ return link($scope)($element)($attrs)(); \
23+
\ } \
24+
\ }; \
25+
\ } " :: EscapeDirective

examples/Todomvc/Focus.purs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
1-
module Todomvc.Focus where
1+
module Todomvc.Focus (FocusDirective(), focus) where
22

33
import Data.Maybe
4-
import Debug.Trace (trace)
54
import Control.Monad (when)
65
import Control.Monad.Eff
76

8-
import DOM.Node (DOM(..), focus)
7+
import qualified DOM.Node as D
98

10-
import Angular.Attributes (Attr(..), get)
11-
import Angular.Directive (LinkFn(..), directive, defn, postLink)
9+
import Angular.Attributes (Attr(), get)
1210
import Angular.Element ((!!))
1311
import Angular.Scope (watch, apply, applyExpr)
1412

15-
focusLink :: forall e a b c d. LinkFn (ngattr :: Attr, dom :: DOM | e) a b c d
16-
focusLink scope element attrs ctrls trans = do
13+
foreign import data FocusDirective :: *
14+
15+
link scope element attrs = do
1716
as <- get attrs
18-
watch as.todoFocus (Just (\a1 _ _ -> do
19-
when a1 $ do
20-
zeroTimeout case element !! 0 of
21-
Just el -> focus el
22-
Nothing -> return unit
23-
return unit
24-
)) false scope
25-
return unit
17+
watch as.todoFocus (Just (\a _ _ -> when a $ zeroTimeout
18+
$ maybe (return unit) D.focus (element !! 0))) false scope
2619

2720
foreign import zeroTimeout
2821
" function zeroTimeout(k) { \
@@ -33,5 +26,11 @@ foreign import zeroTimeout
3326
\ }"
3427
:: forall e. Eff e Unit -> Eff e Unit
3528

36-
focusDirective m =
37-
directive "todoFocus" m $ return defn { link = postLink focusLink }
29+
foreign import focus
30+
" /*@ngInject*/function focus(){ \
31+
\ return { \
32+
\ link: function($scope, $element, $attrs){ \
33+
\ return link($scope)($element)($attrs)(); \
34+
\ } \
35+
\ }; \
36+
\ } " :: FocusDirective

examples/Todomvc/Main.purs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
module Todomvc.Main where
22

3-
import Angular.Module (newModule)
3+
import Angular.Module (controller, directive, ngmodule')
44

5-
import Todomvc.Controller (todoController)
6-
import Todomvc.Escape (escapeDirective)
7-
import Todomvc.Focus (focusDirective)
5+
import Todomvc.Controller (todoctrl)
6+
import Todomvc.Escape (escape)
7+
import Todomvc.Focus (focus)
88

99
main = do
10-
m <- newModule "todomvc" []
11-
todoController m
12-
escapeDirective m
13-
focusDirective m
10+
m <- ngmodule' "todomvc" []
11+
controller "TodoCtrl" todoctrl m
12+
directive "todoEscape" escape m
13+
directive "todoFocus" focus m

src/Angular.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ module Angular where
22

33
import Control.Monad.Eff
44

5-
import Angular.Injector (Injector(..))
6-
import Angular.Element (Element(..))
5+
import Angular.Injector (Injector())
6+
import Angular.Element (Element())
77

88
-- | bind
99

src/Angular/Attributes.purs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
module Angular.Attributes where
1+
module Angular.Attributes
2+
( Attributes()
3+
, Attr()
4+
, addClass
5+
, removeClass
6+
, updateClass
7+
, observe
8+
, set
9+
, get
10+
, attr
11+
) where
212

313
import Control.Monad.Eff
414

src/Angular/Cache.purs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
module Angular.Cache
2-
( Cache(..)
3-
, CacheFactory(..)
4-
, CACHE(..)
5-
, Key(..)
6-
, Name(..)
7-
, Options(..)
8-
, injCacheFactory
2+
( Cache()
3+
, CacheFactory()
4+
, CACHE()
5+
, Key()
6+
, Name()
7+
, Options()
98
, cache
109
, put
1110
, get
@@ -18,8 +17,6 @@ module Angular.Cache
1817
import Control.Monad.Eff
1918
import Data.Maybe
2019

21-
import Angular.Injector (InjectDependency(..))
22-
2320
foreign import data CACHE :: !
2421

2522
foreign import data Cache :: *
@@ -32,13 +29,6 @@ type Name = String
3229

3330
type Options a = { capacity :: Number | a }
3431

35-
foreign import injCacheFactory
36-
" function injCacheFactory(){ \
37-
\ var $injector = angular.element(document).injector(); \
38-
\ return $injector.get('$cacheFactory'); \
39-
\ } "
40-
:: forall e. Eff (nginj :: InjectDependency | e) CacheFactory
41-
4232
foreign import cache
4333
" function cache(name){ \
4434
\ return function(opts){ \

0 commit comments

Comments
 (0)