Get 'Ref' of a ReactBridgeComponent
Closed this issue · 5 comments
Hi There,
Is it possible to get Ref
of ReactBridgeComponent
? Just we can use withRef
with any other component?
Regards,
Syed
Hi Syed,
it seems that we have examples of this
ComposedTextField
NativeSelects
SimpleSelect
I think this can be done in several ways:
- You can do this by binding to the component id tag as in the examples above.
- You can use untypedRef, for example:
object ComposedTextField extends ScalaCssReactImplicits {
...
class Backend(t: BackendScope[Props, State]) {
var inputRef: AnyRef = null
def mount = t.modState(_.setLabelWidth(inputRef.asInstanceOf[Element])) >> t.forceUpdate
def render(props: Props, state: State): VdomElement = {
div(
...
MuiFormControl(variant = MuiFormControl.Variant.outlined)(css.formControl,
MuiInputLabel()(htmlFor := "component-outlined", untypedRef(inputRef = _), "Name"),
MuiOutlinedInput(labelWidth = state.labelWidth)(
id := "component-outlined",
value := state.name,
onChange ==> handleChange,
)
),
...
)
}
}
}
- You can't use withRef directly to ReactBridgeComponent, but you can do it by wrapping it in a ScalaComponent, for example:
object ComposedTextField extends ScalaCssReactImplicits {
case class State(
...
labelWidth: Int = 0
) {
...
def setLabelWidth(offsetWidth: Int) = copy(labelWidth = offsetWidth)
}
...
val InputLabelComponent = ScalaComponent.builder[Unit]
.renderStatic(MuiInputLabel()(htmlFor := "component-outlined", "Name"))
.build
class Backend(t: BackendScope[Props, State]) {
private val inputRef = Ref.toScalaComponent(InputLabelComponent)
def mount = inputRef.foreachCB { ref =>
val offsetWidth = ref.getDOMNode.asMounted().asHtml().offsetWidth.toInt
t.modState(_.setLabelWidth(offsetWidth))
}
def render(props: Props, state: State): VdomElement = {
div(
...
MuiFormControl(variant = MuiFormControl.Variant.outlined)(css.formControl,
InputLabelComponent.withRef(inputRef)(),
MuiOutlinedInput(labelWidth = state.labelWidth)(
id := "component-outlined",
value := state.name,
onChange ==> handleChange,
)
),
...
)
}
}
}
Hi Alexey,
Thanks for your reply.
How would you define a ref for a component that defines a function. After getting the ref you need to call function on the ref.
For example, in https://www.primefaces.org/primereact/showcase/#/toast, only way to communicate with the Toast
is to get the ref and call show
function.
Regards,
Syed
Well, you can't do it through ReactBridgeComponent right now. Improvements are required for it.
If you do this directly through scalajs-react, then in a draft version it looks something like this:
import scala.scalajs.js
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.annotation.JSImport
import japgolly.scalajs.react.vdom.all._
import japgolly.scalajs.react.{BackendScope, Children, JsComponent, Ref, ScalaComponent}
object ToastExample {
@js.native
trait ToastMessage extends js.Object {
var severity: String = js.native
var summary: String = js.native
var detail: String = js.native
var sticky: Boolean = js.native
}
object ToastMessage {
def apply(
severity: String,
summary: String,
detail: String,
sticky: Boolean
) = {
val o: Map[String, Any] = Map(
"severity" -> severity,
"summary" -> summary,
"detail" -> detail,
"sticky" -> sticky
)
o.toJSDictionary.asInstanceOf[js.Object].asInstanceOf[ToastMessage]
}
}
object Toast {
@JSImport("primereact/components/toast/Toast", "Toast")
@js.native
object RawComponent extends js.Function
@js.native
trait Props extends js.Object {
var position: String = js.native
}
@js.native
trait JsMethods extends js.Object {
def show(message: js.Array[ToastMessage]): Unit = js.native
def show(message: ToastMessage): Unit = js.native
def clear(): Unit = js.native
}
def props(position: String): Props = {
val p = (new js.Object).asInstanceOf[Props]
p.position = position
p
}
val component = JsComponent[Props, Children.None, Null](RawComponent).addFacade[JsMethods]
}
class Backend(t: BackendScope[Unit, Unit]) {
private val toastRef = Ref.toJsComponentWithMountedFacade[Toast.Props, Null, Toast.JsMethods]
def showSuccess() = {
val message = ToastMessage("success", "Success Message", "Message Content", sticky = true)
toastRef.foreach(_.raw.show(message))
}
def render(): VdomElement = {
div(
Toast.component.withRef(toastRef)(Toast.props(position = "top-left")),
button(onClick --> showSuccess(), "Success")
)
}
}
private val component = ScalaComponent.builder[Unit]("ToastExample")
.renderBackend[Backend]
.build
def apply() = component()
}
Hi Alexey,
Thanks for reply, I would try this.
Regards,
Syed
Hi Alexey,
Thanks for your reply, I tried the code snippet as you mentioned and it worked.
I am closing this issue.
Regards,
Syed