Как построить мод Bootstrap React, используя Scala Js React - PullRequest
1 голос
/ 09 июля 2019

Как мне создать Модальный компонент из библиотеки React Bootstrap с помощью библиотеки Scala.js React?

1 Ответ

0 голосов
/ 10 июля 2019

Тот факт, что модал должен изменить состояние (show = true / false), чтобы показать / скрыть диалог, сделал решение нетривиальным. Я решил это, обернув его в компонент, имеющий логическое состояние, которое можно изменить, и когда его нужно показать / скрыть, я меняю состояние с нечистыми эффектами.

Другая проблема заключалась в том, что, если у Модала есть кнопки, которые должны изменить состояние, их обработчики событий должны каким-то образом получить доступ к этому состоянию. Я решил эту проблему, предоставив пользователям компонента доступ к Backend компонента при создании.

Вот моя реализация Модал:

class Modal(bs: BackendScope[Unit, Boolean], onHide: => Unit, children: Modal => Seq[ChildArg]) {

  def render(show: Boolean) = {
    val props = (new js.Object).asInstanceOf[Modal.Props]
    props.show = show
    props.onHide = () => {
        dismiss()
        onHide
    }

    Modal.component(props)(children(this): _*)
  }

  def dismiss() = {
    bs.withEffectsImpure.setState(false)
  }
}

object Modal {

  @JSImport("react-bootstrap", "Modal")
  @js.native
  object RawComponent extends js.Object

  @js.native
  trait Props extends js.Object {
    var show: Boolean = js.native
    var onHide: js.Function0[Unit] = js.native
  }

  val component = JsComponent[Props, Children.Varargs, Null](RawComponent)

  type Unmounted = Scala.Unmounted[Unit, Boolean, Modal]

  def apply(onHide: => Unit = Unit)(children: Modal => Seq[ChildArg]): Unmounted =   {
    val component = ScalaComponent.builder[Unit]("Modal")
    .initialState(true)
    .backend(new Modal(_, onHide, children))
    .renderBackend
    .build
    component()
  }
}

И объект Dialog, который его использует:

object Dialog {
  object Response extends Enumeration {
    type Response = Value
    val OK, CANCEL = Value
  }

  import Response._

  def prompt(title: String, body: String, okText: String): Future[Response] = {

    // Add an element into which we render the dialog
    val element = dom.document.body.appendChild(div(id := "dialog").render).asInstanceOf[Element]

    // Create a promise of a return and a method to send it
    val p = Promise[Response]
    def respond(ret: Response) = {
        // Remove the containing element and return the response
        dom.document.body.removeChild(element)
        p.success(ret)
    }

    Modal(respond(Response.CANCEL)) { modal =>

        // Function to dismiss the dialog and respond
        def quit(ret: Response) = {
            modal.dismiss()
            respond(ret)
        }

        // Create the components for our Modal
        Seq(
            ModalHeader(true,
                ModalTitle(title)
            ),
            ModalBody(body),
            ModalFooter(
                Button(variant = "secondary", onClick = () => { quit(Response.CANCEL) })("Cancel"),
                Button(variant = "primary", onClick = () => { quit(Response.OK) })(okText)
            )
        )
    }.renderIntoDOM(element).backend

    p.future
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...