Bây giờ chúng ta sẽ xem xét một ví dụ sẵn có trong tài liệu hướng dẫn online của Elm
có tên là các nút nhấn Buttons
. Ví dụ này cũng chính là ví dụ trong tấm hình mô phỏng kiến trúc cơ bản của Elm
ở phần đầu tiên của bài viết trước. Trình tự thực hiện ví dụ của chúng ta sẽ là make it work
rồi mới make it nice
. Và đoạn thêm code CSS để khiến các thành phần dễ nhìn hơn chúng ta sẽ để sau cùng, khi các thành phần đã có thể hoạt động tốt.
Abstraction
Chúng ta sẽ có một div
hiển thị một giá trị số nguyên, kèm theo 2 nút nhấn +
và -
để thực hiện chức năng tăng/giảm giá trị được hiển thị.
Khởi đầu thì chúng ta cần xác định kết quả output
của chương trình. Và trong module Browser
thì ở ngay phần đầu Elm
khuyến khích sử dụng trình Browser.sandbox
để học tương tác căn bản. Chương trình này chỉ yêu cầu đúng bộ tham số đầu vào tối thiểu là một Record { init, view, update }
mà chúng ta đã nói trong phần giới thiệu kiến trúc Elm Architecture
căn bản.
Như vậy nếu như chúng ta đặt tên cho chương trình là Buttons
và đóng gói trong một module
riêng thì chương trình Main
sẽ cố định là như thế này:
1 2 3 4 5 6 7 | <span class="token keyword">module</span> <span class="token constant">Main</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span><span class="token hvariable">main</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Browser <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Buttons <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token hvariable">main</span> <span class="token operator">:</span> <span class="token constant">Program</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token constant">Model</span> <span class="token constant">Message</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">Browser.sandbox</span> <span class="token punctuation">(</span><span class="token constant">Buttons</span> <span class="token hvariable">init</span> <span class="token hvariable">view</span> <span class="token hvariable">update</span><span class="token punctuation">)</span> |
Ở đây các tên định danh kiểu bản ghi Model
, kiểu tin nhắn sự kiện Message
, trình khởi tạo bản ghi Buttons
, và các chương trình init
, view
, update
, tất cả đều sẽ được định nghĩa trong module Buttons
.
1 2 3 4 | <span class="token keyword">module</span> <span class="token constant">Buttons</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span><span class="token constant">Buttons</span><span class="token punctuation">)</span> <span class="token keyword">type</span> <span class="token keyword">alias</span> <span class="token constant">Buttons</span> <span class="token operator">=</span> <span class="token constant">Nothing</span> |
Để tạo bản ghi sử dụng cho Browser.sandbox
thì chúng ta cần xem qua cấu hình của chương trình con này một chút.
1 2 3 4 5 6 7 | <span class="token hvariable">sandbox</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token hvariable">init</span> <span class="token operator">:</span> <span class="token hvariable">model</span> <span class="token punctuation">,</span> <span class="token hvariable">view</span> <span class="token operator">:</span> <span class="token hvariable">model</span> <span class="token operator">-></span> <span class="token constant">Html</span> <span class="token hvariable">msg</span> <span class="token punctuation">,</span> <span class="token hvariable">update</span> <span class="token operator">:</span> <span class="token hvariable">msg</span> <span class="token operator">-></span> <span class="token hvariable">model</span> <span class="token operator">-></span> <span class="token hvariable">model</span> <span class="token punctuation">}</span> <span class="token operator">-></span> <span class="token constant">Program</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token hvariable">model</span> <span class="token hvariable">msg</span> |
Như vậy là chúng ta sẽ cần một bản ghi Record
có chứa các chương trình init
, view
, update
như trên. Theo phương cách suy nghĩ đệ quy recursion
thì chúng ta sẽ tạm dừng cái trình khởi tạo Buttons
như trên để định nghĩa các sub-program
trước.
Và để kiểm tra hoạt động của các chương trình con trong module
, chúng ta sẽ chưa thể sử dụng elm reactor
mà sẽ cần phải tương tác với elm repl
.
1 2 3 | cd Documents && cd learn-elm elm repl |
Init
Đầu tiên là init
– chương trình khởi tạo bản ghi dữ liệu Model
để sử dụng cho view
bày ra giao diện người dùng. Như vậy chúng ta sẽ cần định nghĩa kiểu bản ghi Model
trước để sử dụng cho init
.
Do chương trình của chúng ta chỉ có một yếu tố duy nhất mang tính cập nhật đó là giá trị số nguyên được hiển thị giữa hai nút nhấn +
và -
, nên chúng ta sẽ có kiểu Model
đơn giản. Và chương trình init
để khởi tạo bản ghi dữ liệu đầu tiên cũng không có gì đáng lưu ý. Không yêu cầu tham số đầu vào và trả về chính xác bản ghi Model
là được.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">module</span> <span class="token constant">Buttons</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span> <span class="token constant">Buttons</span> <span class="token punctuation">,</span> <span class="token constant">Model</span> <span class="token punctuation">,</span> <span class="token hvariable">init</span> <span class="token punctuation">)</span> <span class="token keyword">type</span> <span class="token keyword">alias</span> <span class="token constant">Buttons</span> <span class="token operator">=</span> <span class="token constant">Nothing</span> <span class="token comment">-- Initializer - - - - - - - - -</span> <span class="token keyword">type</span> <span class="token keyword">alias</span> <span class="token constant">Model</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token hvariable">value</span> <span class="token operator">:</span> <span class="token constant">Int</span> <span class="token punctuation">}</span> <span class="token hvariable">init</span> <span class="token operator">:</span> <span class="token constant">Model</span> <span class="token hvariable">init</span> <span class="token operator">=</span> <span class="token constant">Model</span> <span class="token number">0</span> |
1 2 3 | <span class="token hvariable">init</span> <span class="token comment">-- { value = 0 } : Model </span> |
View
Tiếp theo là view
– chương trình cấu trúc template HTML
để dựng giao diện người dùng. Ở đây chúng ta cũng đồng thời định nghĩa các kiểu tin nhắn sự kiện Message
để mô tả ý nghĩa thao tác của người dùng. Và với tính năng tương tác của hai nút nhấn tăng/giảm giá trị như dự kiến thì chúng ta sẽ có hai kiểu tin nhắn tương ứng là Increment
và Decrement
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <span class="token keyword">module</span> <span class="token constant">Buttons</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html.Events <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html.Attributes <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token comment">-- type alias Buttons = Nothing</span> <span class="token comment">-- Initializer ...</span> <span class="token comment">-- Templater - - - - - - - - -</span> <span class="token keyword">type</span> <span class="token constant">Message</span> <span class="token operator">=</span> <span class="token constant">Increment</span> <span class="token operator">|</span> <span class="token constant">Decrement</span> <span class="token hvariable">view</span> <span class="token operator">:</span> <span class="token constant">Model</span> <span class="token operator">-></span> <span class="token constant">Html</span> <span class="token constant">Message</span> <span class="token hvariable">view</span> <span class="token hvariable">model</span> <span class="token operator">=</span> <span class="token keyword">let</span> <span class="token hvariable">value</span> <span class="token operator">=</span> <span class="token hvariable">String.fromInt</span> <span class="token hvariable">model</span><span class="token punctuation">.</span><span class="token hvariable">value</span> <span class="token keyword">in</span> <span class="token hvariable">div</span> <span class="token punctuation">[</span> <span class="token hvariable">attribute</span> <span class="token string">"id"</span> <span class="token string">"app"</span> <span class="token punctuation">]</span> <span class="token punctuation">[</span> <span class="token hvariable">button</span> <span class="token punctuation">[</span> <span class="token hvariable">onClick</span> <span class="token constant">Decrement</span> <span class="token punctuation">]</span> <span class="token punctuation">[</span> <span class="token hvariable">text</span> <span class="token string">"-"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token hvariable">div</span> <span class="token punctuation">[</span> <span class="token hvariable">attribute</span> <span class="token string">"id"</span> <span class="token string">"out"</span> <span class="token punctuation">]</span> <span class="token punctuation">[</span> <span class="token hvariable">text</span> <span class="token hvariable">value</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token hvariable">button</span> <span class="token punctuation">[</span> <span class="token hvariable">onClick</span> <span class="token constant">Increment</span> <span class="token punctuation">]</span> <span class="token punctuation">[</span> <span class="token hvariable">text</span> <span class="token string">"+"</span> <span class="token punctuation">]</span> <span class="token punctuation">]</span> |
Ở đây phần id="app"
và id="out"
mình sử dụng để làm bộ chọn cho code CSS sau khi đã hoàn thành logic hoạt động.
1 2 3 | <span class="token hvariable">view</span> <span class="token punctuation">(</span><span class="token constant">Model</span> <span class="token number">1001</span><span class="token punctuation">)</span> <span class="token comment">-- <internals> : Html.Html Message</span> |
Có lẽ là view
đã có thể hoạt động tốt. Tuy nhiên nếu như bạn muốn kiểm tra kết quả hiển thị thì có thể viết thêm một chương trình main
ngay trong module Buttons
và mở tệp Buttons.elm
trong elm reactor
.
1 2 3 4 5 6 7 8 | <span class="token comment">-- Initializer ...</span> <span class="token comment">-- Templater - - - - - - - - -</span> <span class="token comment">-- view : ...</span> <span class="token hvariable">main</span> <span class="token operator">:</span> <span class="token constant">Html</span> <span class="token constant">Message</span> <span class="token hvariable">main</span> <span class="token operator">=</span> <span class="token hvariable">view</span> <span class="token punctuation">(</span><span class="token constant">Model</span> <span class="token number">1001</span><span class="token punctuation">)</span> |
Chúng ta vẫn sẽ cần sử dụng tới elm repl
vì vậy nên bạn hãy mở thêm một cửa sổ dòng lệnh khác cho elm reactor
.
1 2 3 | cd Documents && cd learn-elm elm reactor |
http://localhost:8000/src/Buttons.elm
Update
Cuối cùng là update
– chương trình này sẽ nhận vào một tin nhắn sự kiện Message
và một bản ghi Model
mô tả dữ liệu đang hiển thị ở thời điểm hiện tại. Sau đó update
sẽ phân tích tin nhắn sự kiện và tạo ra một bản ghi Model
mới với giá trị tăng hoặc giảm 1 đơn vị.
1 2 3 4 5 6 7 8 9 10 | <span class="token comment">-- Initializer ...</span> <span class="token comment">-- Templater ...</span> <span class="token comment">-- Updater - - - - - - - - -</span> <span class="token hvariable">update</span> <span class="token operator">:</span> <span class="token constant">Message</span> <span class="token operator">-></span> <span class="token constant">Model</span> <span class="token operator">-></span> <span class="token constant">Model</span> <span class="token hvariable">update</span> <span class="token hvariable">message</span> <span class="token hvariable">model</span> <span class="token operator">=</span> <span class="token keyword">case</span> <span class="token hvariable">message</span> <span class="token keyword">of</span> <span class="token constant">Increment</span> <span class="token operator">-></span> <span class="token constant">Model</span> <span class="token punctuation">(</span><span class="token hvariable">model</span><span class="token punctuation">.</span><span class="token hvariable">value</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token constant">Decrement</span> <span class="token operator">-></span> <span class="token constant">Model</span> <span class="token punctuation">(</span><span class="token hvariable">model</span><span class="token punctuation">.</span><span class="token hvariable">value</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> |
1 2 3 4 5 6 | <span class="token hvariable">update</span> <span class="token constant">Increment</span> <span class="token punctuation">(</span><span class="token constant">Model</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">-- { value = 1 } : Model</span> <span class="token hvariable">update</span> <span class="token constant">Decrement</span> <span class="token punctuation">(</span><span class="token constant">Model</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token comment">-- { value = -1 } : Model</span> |
Buttons
Như vậy là tất cả các sub-program
đều đã hoạt động tốt. Bây giờ chúng ta chỉ cần hoàn thành nốt định nghĩa bản ghi Buttons
và chạy thử chương trình trong elm reactor
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">module</span> <span class="token constant">Buttons</span> <span class="token keyword">exposing</span> <span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html.Events <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token import-statement"><span class="token keyword">import</span> Html.Attributes <span class="token keyword">exposing</span> </span><span class="token punctuation">(</span><span class="token operator">..</span><span class="token punctuation">)</span> <span class="token keyword">type</span> <span class="token keyword">alias</span> <span class="token constant">Buttons</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token hvariable">init</span> <span class="token operator">:</span> <span class="token constant">Model</span> <span class="token punctuation">,</span> <span class="token hvariable">view</span> <span class="token operator">:</span> <span class="token constant">Model</span> <span class="token operator">-></span> <span class="token constant">Html</span> <span class="token constant">Message</span> <span class="token punctuation">,</span> <span class="token hvariable">update</span> <span class="token operator">:</span> <span class="token constant">Message</span> <span class="token operator">-></span> <span class="token constant">Model</span> <span class="token operator">-></span> <span class="token constant">Model</span> <span class="token punctuation">}</span> <span class="token comment">-- Initializer ...</span> <span class="token comment">-- Templater ...</span> <span class="token comment">-- Updater ...</span> |
http://localhost:8000/src/Main.elm
Sau khi click thử vào các nút +
và -
, nếu như bạn thấy mọi thứ đã hoạt động ổn cả thì có thể nhấn Ctrl+C
để dừng elm reactor
và chạy lệnh elm make
.
1 2 3 4 5 | elm make src/Main.elm Success! Main ───> index.html |
Bây giờ bạn có thể gắn thêm một <link href="style.css">
vào tệp index.html
vừa được tạo ra và thêm một đoạn code CSS trước khi mở tệp này trực tiếp bằng trình duyệt web để kiểm tra hoạt động.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span class="token selector">*</span> <span class="token punctuation">{</span> <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span> <span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector">#app</span> <span class="token punctuation">{</span> <span class="token property">border</span><span class="token punctuation">:</span> 1px solid lightgray<span class="token punctuation">;</span> <span class="token property">border-radius</span><span class="token punctuation">:</span> 5px<span class="token punctuation">;</span> <span class="token property">display</span><span class="token punctuation">:</span> inline-block<span class="token punctuation">;</span> <span class="token property">margin</span><span class="token punctuation">:</span> 27px 45px<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span> 9px<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector">#app button</span> <span class="token punctuation">{</span> <span class="token property">font-size</span><span class="token punctuation">:</span> 21px<span class="token punctuation">;</span> <span class="token property">border-radius</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span> <span class="token property">border</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span> 12px 21px<span class="token punctuation">;</span> <span class="token property">margin</span><span class="token punctuation">:</span> 0 2px<span class="token punctuation">;</span> <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector">#out</span> <span class="token punctuation">{</span> <span class="token property">font-size</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span> <span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span> <span class="token property">display</span><span class="token punctuation">:</span> inline-block<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span> 9px 24px<span class="token punctuation">;</span> <span class="token property">min-width</span><span class="token punctuation">:</span> 90px<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Oh… và đó là trình tự để tạo ra một element
với kiến trúc Elm Architecture
. Mặt khác thì Browser.sandbox
sẽ giới hạn element
này không thể tương tác với môi trường bên ngoài. Như vậy sẽ rất an toàn để bạn thử tạo ra một vài element
như các danh sách dạng sổ xuống dropdown
hay trình chiếu ảnh carousel
để chèn vào trang web mà bạn đã xây dựng trước đó.
1 2 | elm make src/Main.elm --output buttons.js |
Để nhúng element
vừa tạo ra vào một trang web mà bạn đã xây dựng trước đó, bạn cần nhúng tệp button.js
và style.css
vào template
của trang web đang có. Và bổ sung thêm một cặp thẻ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>style.css<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span> <span class="token comment"><!-- somewhere in --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>elm-buttons<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token comment"><!-- the document --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"> <span class="token keyword">const</span> app <span class="token operator">=</span> Elm<span class="token punctuation">.</span>Buttons<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">{</span> node<span class="token operator">:</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"elm-buttons"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>elm.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> |
Trong trường hợp bạn muốn tạo ra các element
có khả năng tương tác với các thành phần bên ngoài hay gửi yêu cầu truy vấn dữ liệu tới server
, thì chúng ta có Browser.element
. Chương trình này sẽ yêu cầu thêm một vài yếu tố khác trong tham số đầu vào để hỗ trợ cho các thao tác truy vấn dữ liệu từ server
được thực thi bất đồng bộ async
. Và như vậy mối quan tâm tiếp theo của chúng ta sẽ là cách gửi các yêu cầu truy vấn HTTP request
và cập nhật kết quả từ các thao tác async
.
Elm Architecture in JS/jQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <span class="token comment">/* -- init - - - - - - - - - */</span> <span class="token comment">// -- Model = { value : any }</span> <span class="token keyword">const</span> <span class="token function-variable function">Model</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> value <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// -- init : number -> Model</span> <span class="token keyword">const</span> <span class="token function-variable function">init</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">Model</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token comment">/* -- view - - - - - - - - - */</span> <span class="token comment">// -- view : Model -> jElement</span> <span class="token keyword">const</span> <span class="token function-variable function">view</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">model</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> <div id="app" data-value="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>model<span class="token punctuation">.</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"> <button> - </button> <div id="out"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>model<span class="token punctuation">.</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </div> <button> + </button> </div> </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token comment">/* -- update - - - - - - - - - */</span> <span class="token comment">// -- Message = Decrement | Increment</span> <span class="token keyword">const</span> Decrement <span class="token operator">=</span> <span class="token string">"decrease"</span> <span class="token keyword">const</span> Increment <span class="token operator">=</span> <span class="token string">"increase"</span> <span class="token comment">// -- update : Message -> Model -> Model</span> <span class="token keyword">const</span> <span class="token function-variable function">update</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">message</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token parameter">model</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>message <span class="token operator">==</span> Decrement<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">Model</span> <span class="token punctuation">(</span>model<span class="token punctuation">.</span>value <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>message <span class="token operator">==</span> Increment<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">Model</span> <span class="token punctuation">(</span>model<span class="token punctuation">.</span>value <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">"any-other-case"</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span> <span class="token punctuation">(</span><span class="token string">"Invalid Message"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">/* -- Buttons - - - - - - - - - */</span> <span class="token comment">// -- Buttons : init -> view -> update -> jElement</span> <span class="token keyword">const</span> <span class="token function-variable function">Buttons</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">init</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token parameter">view</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token parameter">update</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">var</span> $app <span class="token operator">=</span> <span class="token function">view</span> <span class="token punctuation">(</span><span class="token function">init</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> $app<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Increment<span class="token interpolation-punctuation punctuation">}</span></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Decrement<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">var</span> value <span class="token operator">=</span> Number<span class="token punctuation">.</span><span class="token function">parseInt</span><span class="token punctuation">(</span>$app<span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"data-value"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> model <span class="token operator">=</span> <span class="token function">update</span> <span class="token punctuation">(</span>event<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token function">Model</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> $app<span class="token punctuation">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string">"data-value"</span><span class="token punctuation">,</span> model<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token punctuation">;</span> $app<span class="token punctuation">.</span><span class="token function">children</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span>model<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> $app<span class="token punctuation">.</span><span class="token function">children</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"click"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> $app<span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span>Decrement<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> $app<span class="token punctuation">.</span><span class="token function">children</span><span class="token punctuation">(</span><span class="token string">"button"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">last</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"click"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> $app<span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span>Increment<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> $app <span class="token punctuation">}</span> <span class="token comment">// -- render the app</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#js-buttons"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token function">Buttons</span> <span class="token punctuation">(</span>init<span class="token punctuation">)</span> <span class="token punctuation">(</span>view<span class="token punctuation">)</span> <span class="token punctuation">(</span>update<span class="token punctuation">)</span><span class="token punctuation">)</span> |
[Declarative Programming + Elm] Bài 12 – Commands & Subscriptions