前回、施設編集ページを作りましたが、まだオープンとクローズ時間の欄しかないので、ほかの情報も編集できるようにビューを作ります。
また同時に、各フィールドに入力された時点でモデルをアップデートするようにしておきます。その時点でデータベースに反映することもできますが、DBアクセスは編集が全て終わってから一度だけにしたいので、ここでは一時的にモデルが更新されるだけです。デバッグコードを入れておくので、入力するたびにコンソールログに結果が表示されます。最後に保存ボタンを置いて、それを押したときにデータベースに反映させる仕組みにしましょう。
先ほどgithubのリポジトリを作ったので、そこからコード全体も見れます。
src/Facilities/SingleEdit.elmの編集
オープン、クローズ、郵便番号、住所、ウェブサイトURL、説明欄の編集ができるようにします。またモデルのアップデートのため、input
タグにvalue
とonInput
を設定しておきます。Msgs.Change...
は、src/Msgs.elm
で定義します。以下、変更部分のみです。今回はgithubへの最初のコミットなので、変更箇所がわかりませんが、次回からはコミット単位で記事を書いて行くつもりなので、githubで変更箇所を確認すれば正確に追えるようなります。
-- いくつかインポート関数が増えた
import Html exposing (button, div, h1, Html, input, p, text, textarea)
import Html.Attributes exposing (class, cols, placeholder, name, rows, size, type_, value)
import Html.Events exposing (onClick, onInput)
-- 編集フォーム
-- オープン・クローズのところにもonInputでのメッセージを追加
editForm : Facility -> Html Msg
editForm model =
let _ = Debug.log "model:" model in
div []
[ div [ class "col col-8 px1"]
[ p []
[ text "Opening time: "
, input [ type_ "time", value model.opening.open, onInput (Msgs.ChangeOpenTime model) ] []
, text " - "
, input [ type_ "time", value model.opening.close, onInput (Msgs.ChangeCloseTime model) ] []
]
, p []
[ text "Postal code (Zip code): "
, input [ type_ "text", value model.postcode, onInput (Msgs.ChangePostCode model) ] []
]
, p []
[ text "Address: "
, input [ type_ "text", size 100, value model.address, onInput (Msgs.ChangeAddress model) ] []
] -- サイズをレスポンシブにしたい
, p []
[ text "URL: "
, input [ type_ "url", size 100, value model.web_site, onInput (Msgs.ChangeWebSite model) ] []
]
, p []
[ text "Description: "
, textarea [ rows 10, cols 100, value model.description, onInput (Msgs.ChangeDescription model)] []
]
, button [] [ text "Submit"]
]
]
src/Msgs.elmの編集
各フィールドの編集時に送信されるメッセージを定義します。どの施設の情報を編集するか(Facility
)と、その値(String
)をメッセージと一緒に送ります。
type Msg
= OnFetchFacilities (WebData (List Facility))
| OnLocationChange Location
| ChangeOpenTime Facility String
| ChangeCloseTime Facility String
| ChangeAddress Facility String
| ChangePostCode Facility String
| ChangeWebSite Facility String
| ChangeDescription Facility String
各メッセージに対応するアップデート処理を追加します。どのフィールドを変更しても、
- 該当する
Facility
の該当箇所の値を更新 - 更新した
Facility
をモデルに反映
という流れは一緒なので、updataFacility
関数を作ってモデルに反映する部分を共通化しました。以下全部。
module Update exposing (..)
import Models exposing (Model, Facility)
import Msgs exposing (Msg(..))
import RemoteData
import Routing exposing (parseLocation)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Msgs.OnFetchFacilities response ->
( { model | facilities = response }, Cmd.none )
Msgs.OnLocationChange location ->
let
newRoute = parseLocation location
in
( { model | route = newRoute }, Cmd.none )
Msgs.ChangeOpenTime facility time ->
let
updatedOpening = { open = time, close = facility.opening.close}
updatedFacility = { facility | opening = updatedOpening }
in
( updateFacility model updatedFacility, Cmd.none )
Msgs.ChangeCloseTime facility time ->
let
updatedOpening = { open = facility.opening.open, close = time}
updatedFacility = { facility | opening = updatedOpening }
in
( updateFacility model updatedFacility, Cmd.none )
Msgs.ChangeAddress facility newAddress ->
let
updatedFacility = { facility | address = newAddress }
in
( updateFacility model updatedFacility, Cmd.none )
Msgs.ChangePostCode facility newPostCode ->
let
updatedFacility = { facility | postcode = newPostCode }
in
( updateFacility model updatedFacility, Cmd.none )
Msgs.ChangeWebSite facility newWebSite ->
let
updatedFacility = { facility | web_site = newWebSite }
in
( updateFacility model updatedFacility, Cmd.none )
Msgs.ChangeDescription facility newDescription ->
let
updatedFacility = { facility | description = newDescription }
in
( updateFacility model updatedFacility, Cmd.none )
--Msgs.ChangeOpeningTime facility ->
-- --let
-- -- updatedFacility = { facility | opening = openingTime }
-- --in
-- ( updateFacility model facility, Cmd.none)
updateFacility : Model -> Facility -> Model
updateFacility model updatedFacility =
let
replace currentFacility =
if currentFacility.id == updatedFacility.id then
updatedFacility
else
currentFacility
updateFacilities facilities = List.map replace facilities
updatedFacilities = RemoteData.map updateFacilities model.facilities
in
{ model | facilities = updatedFacilities }
yarn startしてlocalhost:3000で確認してみましょう。ブラウザのコンソールログを確認すると、フィールドに入力するたびにモデルがアップデートされているのがわかります。デバッグコードはsrc/Facilities/SingleEdit.elm
の30行目に入れています。ただ、冒頭にも書きましたが、ここでは画面上で一時的に変更している状態なのでデータベースには反映されません。リロードすると元に戻ります。
次回は、これをデータベースに反映させる処理を作ります。