The DSL Context solves two situation in projects with Beagle:
When you start a context, you populate a map with key/value and this value is any object (Any)
and if you need to alter them, you have to use the SetContext()
method, check out below:
context = ContextData("myBoolean", false),
onInit = listOf(
SetContext(
contextId = "myBoolean",
value = true
)
The DSL Context solves 3 types of context:
Local
Global
Implicit
The DSL Context works through an annotation process, where the extensions are generated from the context classes that are annotated with @ContextObject and to each property 2 extensions are created:
expression
: Used to rescue the Bind.Expression containing its values.change
: Used to alternate this property value.// generated extensions
public val MyContext.valueExpression: Bind.Expression<String>
get() = expressionOf("@{$id.value}")
public fun MyContext.changeValue(value: String): SetContext {
val contextIdSplit = splitContextId(id)
return SetContext(
contextId = contextIdSplit.first,
path = "${if (contextIdSplit.second != null) "${contextIdSplit.second}." else ""}value",
value = value
)
}
Use the @ContextObject annotation in data classes you want to attribute as context and then they should implement an interface called Context
which has an ID tag.
All the subtypes that the context has must be annotated. See below:
@ContextObject
data class MyContext(
override val id: String,
val value: String = "",
val person: Person = Person("")
) : Context
The extensions expression
and change
were generated to the value and person properties in the file called MyContextNormalizer, check out:
public val MyContext.valueExpression: Bind.Expression<String>
get() = expressionOf("@{$id.value}")
public fun MyContext.changeValue(value: String): SetContext {
val contextIdSplit = splitContextId(id)
return SetContext(
contextId = contextIdSplit.first,
path = "${if (contextIdSplit.second != null) "${contextIdSplit.second}." else ""}value",
value = value
)
}
public fun MyContext.changeValue(value: Bind.Expression<String>): SetContext {
val contextIdSplit = splitContextId(id)
return SetContext(
contextId = contextIdSplit.first,
path = "${if (contextIdSplit.second != null) "${contextIdSplit.second}." else ""}value",
value = value
)
}
public val MyContext.personExpression: Bind.Expression<Person>
get() = expressionOf("@{$id.person}")
public fun MyContext.changePerson(person: Person): SetContext {
val contextIdSplit = splitContextId(id)
return SetContext(
contextId = contextIdSplit.first,
path = "${if (contextIdSplit.second != null) "${contextIdSplit.second}." else ""}person",
value = person
)
}
public fun MyContext.changePerson(person: Bind.Expression<Person>): SetContext {
val contextIdSplit = splitContextId(id)
return SetContext(
contextId = contextIdSplit.first,
path = "${if (contextIdSplit.second != null) "${contextIdSplit.second}." else ""}person",
value = person
)
}
To start a Local Context, create a data class
instance and you need to attribute a context to some component:
private var myContext = MyContext("myContext",
person = Person(
id = "person",
firstName = "firstName local",
lastName = "lastName local")
)
Container(context = myContext)
If you access the expression of some property, use the extesion expression:
Text(myContext.valueExpression),
Text(myContext.person.firstNameExpression),
Text(myContext.person.lastNameExpression)
If you want to alter the value of one of the properties, use the extension change:
myContext.person.changeFirstName("new first name")
myContext.changeValue("new value")
To create a global context, create a data class
annotated with the @GlobalContext:
@GlobalContext
data class GlobalObject(
val street: String = "",
val person: Person = Person("")
)
The extensions are created to each property in its global context, then you are able to access them and alter their values.
data class
can exist with @GlobalContext.To use the global context, start a new data class
instance annotated with @GlobalContext. Through these extensions, you can access/alter the values of this context, see how to do it:
var globalObject = GlobalObject()
globalObject.change(
GlobalObject("Street A",
Person("", "first name global", "last name global"))),
globalObject.person.change(Person("", "firstName global changed", "lastName global changed"))
The implicit context through a lambda
receives a defined object as parameter, this is for you to access the possible values it receives and manipulate/attribute to other contexts.
For you to declared an implicit context:
This method receives the same parameters defined in the Widget, but the properties that have the implicit context annotation are altered to a lambda and receive as a parameter an object or a data class that inherits a context and returns the same defined Widget type. See below:
@RegisterWidget
class Input(
val hint: Bind<String>,
@ImplicitContext
val onTextChange: List<Action>? = null
) : Widget()
//gerado
public fun input(hint: Bind<String>, onTextChange: ((java.lang.String) -> List<Action>)? = null):
Input = Input(hint, onTextChange?.invoke(java.lang.String("onTextChange")))
input(
hint = valueOf(""),
onTextChange = {
listOf(
myContext.changeValue(expressionOf("@{${it}}"))
)
}
)
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.