hailong
hailong

Reputation: 51

How to render json result from api request using Binding.scala

I tried the following code to render json into dom but failed

       <div class="row">
        {val result = FutureBinding(ApiHomeProjectsGet.request())
      result.bind match {
        case None => <div>Loading...</div>
        case Some(Success(ApiHomeProjectsGetResponse200(projects))) =>     {
          for (project <- projects.items) yield <p> {project.title} </p>
        }
        case e => <div>Error</div>
      }}
      </div>

projects is defined as a case class

case class Projects(items: ArrayBuffer[Project])

the compiler reports error:

overloaded method value domBindingSeq with alternatives:
[error]   (text: String)com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Text] <and>
[error]   (node: org.scalajs.dom.raw.Node)com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Node] <and>
[error]   (seq: Seq[org.scalajs.dom.raw.Node])com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Node] <and>
[error]   (bindingSeq: com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node])com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node]
[error]  cannot be applied to (Object)
[error]           <div class="row">
[error]            ^
[error] one error found

How can I render json data from api request to dom with the for(...) yield pattern?


The best solution

     case Some(Success(ApiHomeProjectsGetResponse200(projects))) =>
        <div class="row">
          {Constants[Project](projects.items:_*).map(item => <p> {item.title} </p>)}
        </div>

Upvotes: 2

Views: 314

Answers (2)

hailong
hailong

Reputation: 51

For now, I can use a render function to solve this problem

          case Some(Success(ApiHomeProjectsGetResponse200(projects))) =>
          val projectsBinding = Vars[Project](projects.items:_*)
          <div>
             { renderProjectPanel(projectsBinding).bind}
          </div>

          @dom def renderProjectPanel(items: Vars[Project]) = {
              for (project <- items) yield <p>{project.title}</p>
          }

even though this needs to add some more code, but it works

Hope someone will give a simpler solution

Upvotes: 0

OlivierBlanvillain
OlivierBlanvillain

Reputation: 7768

According to your definition of Projects, projects.items is of type ArrayBuffer[Project]. Your for comprehension desugars to map, the result is therefore of type ArrayBuffer[dom.raw.Node].

In your pattern matching expression you are mixing dom.raw.Node and ArrayBuffer[dom.raw.Node], the least upper bound of these two types is Object which is why it pops up in the error message.

One way to solve this problem would be to return a dom.raw.Node in every branch of the pattern matching, for example:

case ... =>
  <div>
    (for (project <- projects.items) yield <p> {project.title} </p>).toSeq
  </div>

Upvotes: 1

Related Questions