建模条件,带有 elm-simple-forms 的嵌套形式

Modeling condition, nested forms with elm-simple-forms

我有一个以 select 开头的表格。根据 selected 的内容,表格会扩展到一个公共的主要部分和一个取决于 selection 的细节部分。

我开始使用单独的细节部分建模

type ProductDetails
    = Book Book.Model
    | Brochure Brochure.Model
    | Card Card.Model

type alias Model =
  { form : Form CustomError Estimate
  , details : ProductDetails      -- a Form CustomerError CardModel / BookModel / ....
  , msg : String
  }

但这变得非常复杂,例如view.

备选方案似乎是有条件地将详细信息添加到主表单模型中 - 例如

type alias Estimate =
  { customer : String
  , project : String
  , product : String
  , details : ProductDetails
  }

在我开始之前,我欢迎其他人的成功经验

如果我没理解错的话,你们有独立的书籍、小册子和卡片模块吗?我不太明白你的模型的目的是什么,但我会这样构造它:

import Book
import Brochure
import Card

type Products
    = Book
    | Brochure
    | Card


type Msg
    = Details Products


type alias Model =
    { selectedProduct : Product
    }


update : Msg -> Model -> Model
update msg model =
    case msg of
        Details prd ->
            Model prd


view : Model -> Html
view model =
    model.selectedProduct.view

所以你可以看到,现在你定义了所有可用的产品,然后你说 Msg 可以是 Details,它会显示详细信息,它的功能是将 Model 中的 selectedProduct 值设置为 selected 产品。您可以使用 selecting 实现:

button [ onClick (Details Book) ] [ text "Book" ]

例如 select 一本书。稍后您想使其动态化,第一直觉应该是能够调用 selected Product.

的视图函数

在其他情况下,您可以定义需要一些字段的视图,每个产品的模型都将包含这些字段,然后您可以使用它们在网站上编写一些信息。

请注意,上面的代码并不是为了工作,它只是为了表达这个想法。

我不熟悉 elm-simple-forms,但这似乎很好地代表了您的表单:

type ProductType
  = TBook
  | TBrochure
  | TCard

type Product
  = Book Book.Model
  | Brochure Brochure.Model
  | Card Card.Model

type alias Model =
  { product : Maybe Product
  , customer : String
  , project : String
  }

type Msg
  = SelectProductType ProductType

init : Model
init =
  { product = Nothing
  , customer = ""
  , project = ""
  }

update : Msg -> Model -> Model
update msg model =
  case msg of
    SelectProductType product ->
      {model | product = 
        case product of
          TBook -> Book Book.init
          TBrochure -> Brochure Brochure.init
          TCard -> Card Card.init
      }

view : Model -> Html Msg
view model =
  case model.product of

    Nothing ->
      myProductTypeSelect

    Just product ->
      withCommonFormInputs
        <| case product of
             Book submodel -> Book.view submodel
             Brochure submodel -> Brochure.view submodel
             Card submodel -> Card.view submodel

Maybe 为您提供了一种在第一种形式(仅 select)和第二种形式(客户详细信息 + selected 产品类型详细信息)之间进行选择的好方法。

Book.view 等给你 Html 你可以添加到常见的情况:

withCommonFormInputs : Model -> Html Msg -> Html Msg
withCommonFormInputs model productInputs =
    div
      []
      [ input [] [] -- customer
      , input [] [] -- project
      , productInputs -- product (Book, Brochure, Card) subform
      ]

我最终使用了各个字段的Dict,并在产品更改时更改了字段。尝试更明确地为每个产品建模会创建比我需要的更多样板。