-
Waypoint 를 이용해 Router 적용web/laminar 2022. 1. 28. 20:36
문제
Waypoint 를 이용해 Router 를 적용해 본다.
http://localhost:9000/search?engine=google&query=bts 입력 했을 때
google 이 선택 체크되고, Search Query 에 bts 가 입력된 화면이 노출되어야 한다.
사용자가 Search Engine 으로 naver 를 선택 체크하고, Search Query 로 iphone 을 입력후 submit 버튼을 눌렀을 때 브라우저 URL 이 http://localhost:9000/search?engine=naver&query=iphone 로 변경되어야 한다.
http://localhost:9000/login 입력 했을 때
코드
import com.raquo.laminar.api.L import com.raquo.laminar.api.L._ import com.raquo.laminar.nodes.ReactiveHtmlElement import com.raquo.waypoint._ import org.scalajs.dom import org.scalajs.dom.html import upickle.default._ class Radio(name: String, items: Seq[String]) { val selectedVar: Var[String] = Var("") val elem: ReactiveHtmlElement[html.Div] = div( cls := "ui form", div( cls := "inline fields", label(name), items.map(item => div( cls := "field", div( cls := "ui radio checkbox", input( typ := "radio", checked <-- selectedVar.signal.map(_ == item), onChange.mapTo(item) --> selectedVar ), label(item) ) ) ) ) ) } class TextInput(name: String, description: String) { val textVar: Var[String] = Var("") val elem: ReactiveHtmlElement[html.Div] = div( label(name), cls := "ui input", input( typ := "text", onMountFocus, value <-- textVar, onInput.mapToValue --> textVar, placeholder := description ) ) } object Main { sealed trait Page case class SearchPage(engine: String, query: Option[String]) extends Page case object LoginPage extends Page implicit val SearchPageRW: ReadWriter[SearchPage] = macroRW implicit val rw: ReadWriter[Page] = macroRW def main(args: Array[String]): Unit = { // path 까지 route 로 사용될 경우 Route.withQuery 사용 val searchRoute = Route.onlyQuery[SearchPage, (String, Option[String])]( encode = searchPage => (searchPage.engine, searchPage.query), decode = args => SearchPage(args._1, args._2), pattern = (root / "search" / endOfSegments) ? (param[String]("engine") & param[String]("query").?) ) val loginRoute = Route.static(LoginPage, root / "login" / endOfSegments) val router = new Router[Page]( routes = List(searchRoute, loginRoute), getPageTitle = (page: Page) => "my title", serializePage = page => write(page)(rw), deserializePage = pageStr => read(pageStr)(rw) )( $popStateEvent = L.windowEvents.onPopState, owner = L.unsafeWindowOwner ) def renderSearchPage($searchPage: Signal[SearchPage]): Div = { val radio = new Radio("Search Engine", List("naver", "google", "yahoo")) val textInput = new TextInput("Search Query: ", "Enter query") div( h3("Search Page"), $searchPage.map(_.engine) --> radio.selectedVar, radio.elem, $searchPage.map(_.query.getOrElse("")) --> textInput.textVar, textInput.elem, br(), button( "Submit", onClick --> (_ => router.pushState(SearchPage(radio.selectedVar.now(), Some(textInput.textVar.now())))) ), div( hr(), div( "selected engine: ", child.text <-- $searchPage.map(_.engine) ), div( "query: ", child.text <-- $searchPage.map(_.query.getOrElse("")) ) ) ) } def renderLoginPage: Div = div( h3("Login Page") ) val splitter = SplitRender[Page, HtmlElement](router.$currentPage) .collectSignal[SearchPage]($searchPage => renderSearchPage($searchPage)) .collectStatic(LoginPage)(renderLoginPage) val content: Div = div( h1("Routing App"), child <-- splitter.$view ) val containerNode = dom.document.getElementById("main_content") render(containerNode, content) } }
'web > laminar' 카테고리의 다른 글
EventStream 의 flatMap vs combineWithFn (0) 2022.10.01 완성 - 메뉴 구현 (0) 2022.01.29 children 으로 List 표현하기 (0) 2022.01.20 Observer 를 사용해 side effect 처리하기 (0) 2022.01.09 Component - TextInput (0) 2022.01.09