Each component in Jaseci UI Kit is rendered within a jsc-app
. After setting up your code, and assuming your jsc-app
component is placed somewhere in your html tree, the next step is to create the markup. We won't be using HTML to create the structure of our webpage, however, in this case, we will use our jsc-app
component to generate the markup using JSON.
Creating a component is simple: at the bare minimum we need to create an object with a component, props, and sections properties. Here's an example of how we can render a Navbar component.
[
{
"component": "Navbar",
"sections": {
"links": [
{
"component": 'NavLink',
"props": {"label": "Home"}
}
]
},
"props": {
"label": "Jaseci",
"background": "red"
},
}
]
In the code above we asked for a Navbar component with a single link element, we set the label of our navbar to 'Jaseci' and the background to 'red'. We also asked for a link within the navbar and for it to be rendered within the links section.
Names are unique values we attach to a component that will allow us to reference it in the future to get the value of its properties.
Sections allow us to place components within another component. It also allows us to place components at specific locations within another component. In our example above, with the navbar component, links is a section specific to the navbar component that allows us to add Link components within the navbar. Some components have sections and some do not, so be sure to review the available sections for each component to know when and where you can place components within another.
Events allow us to interact with our markup. Just like we can generate the structure of our webpage using props to control the styling and content of our components we can use events to add logic and functionality to make our site interactive. Let's have a look at how we can add an event to our navbar component.
Let's assume we want to display an alert message when a link is clicked: we can modify our link component to listen to an onClick event we can perform an action when we click on the link component.
Taking the code from our example above, let's modify it, we'll start by adding an events property to our link component, and within that events property, our action. Let's do it.
[
{
"name": "nav",
"component": "Navbar",
"sections": {
"links": [
{
"component": 'NavLink',
"props": { "label": 'Home' }
"events": {
"onClick": [
{
"fn": "alert",
"args": ["Jaseci"]
}
]
}
}
]
},
"props": {
"label": "Jaseci"
},
}
]
After adding the code above, whenever we click on the Home link we are going see the message "Jaseci" printed in an alert dialog.
Actions allow us to run arbitrary javascript functions and built-in functions provided by the ui kit in response to certain events. You can perform multiple actions, one after the other, or compose actions to perform an action after another completes, or fails.
In the example above we created an alert action in response to an onClick
event. Let's take a closer look at what we did.
To create an action we need to create an object with the fn
property and the args
property.
- fn - the name of the function we want to call
- args - the values we pass to the function as arguments
Here what our action looked like.
"onClick": [
{
"fn": "alert",
"args": ["Jaseci"]
}
]
What if we wanted to update a property instead? We can changing our action function to update
along provide its two args: the property we want to update and the value of the property.
Here what our action looks like now.
"onClick": [
{
"fn": "update",
"args": ["nav.label", "Jaseci 2.0"]
}
]
Assuming this onClick
event is still attached to our nav link component, whenever we click on this link the label of the navbar will change from Jaseci
to Jaseci 2.0
.
Consider the following code.
"onClick": [
{
"fn": "update",
"args": ["nav.label", "Jaseci 2.0"],
"cond": ['var(nav.label)::#neq::Jaseci 2.0'],
}
]
What have you noticed? It works the same as before, however, there's now a cond
property, this property allow us to prevent the execution of some actions unless a certain condition is satisfied. Each condition is a string. In this example, if we click update and the label is not already Jaseci 2.0
the action will run, if is Jaseci 2.0
, it remain the same.
We can provide multiple conditions to an action and the action will only run if all conditions are satisfied.
We can run until another is executed. We can do so by providing an action as the value to the onCompleted
property of another action. Here's an example using the code above:
"onClick": [
{
"fn": "update",
"args": ["nav.label", "Jaseci 2.0"],
"cond": ['var(nav.label)::#neq::Jaseci 2.0'],
"onCompleted": {
"fn": "alert",
"args": ["Navbar title updated."]
}
}
]
Also consider the following code.
"onClick": [
{
"fn": "update",
"args": ["nav.label", "Jaseci 2.0"],
"cond": ['var(nav.label)::#neq::Jaseci 2.0']
},
{
"fn": "alert",
"args": ["Navbar title updated."]
}
]
In the first code above, we ask for an alert dialog to display after the update
action is finished. But what about the second code, doesn't it work the same? In this case, yes, but also no. Taking a closer lock at the update
action of the first code, it has a cond
, this condition will also prevent the onCompleted
action from running if the update
function did not run. The second code will give us an alert dialog even if the update function did not run.
Operations are "custom actions" that we can create that will allow us to reuse a particular sequence of actions across components. Each operation has a name and can optionally accept a number of arguments.
Take a look at the following example:
[
{
"component": "Container",
"name": "container1",
"operations": {
"sayHi": {
"args": [
"message"
],
"run": [
{
"fn": "alert",
"args": [
"arg(message) cool!"
]
}
]
}
}
},
{
"component": "Button",
"events": {
"onClick": [
{
"fn": "runOperation",
"operation": "container1.sayHi",
"args": [
"Hello world!"
]
}
]
},
"props": {
"name": "btn1",
"label": "Say Hello"
}
}
]
In the example above, we defined an operation within the container1
component then we called this operation in the btn1
component. Each operation is called using the callOperation
action. The callOperation
action requires the operation
property to be defined with a valid operation as its value. An operation is referenced using the format [Component Name].[Operation Name]
which translates to container1.sayHi
in this case.
When defining an operation we can set the args
property to a list of strings. This can be used to accept args to your operation. Each arg can be used in the actions within an operation and will be replaced by the values passed in the args of the callOperation
action. In the example above, arg(message)
is replaced with 'Hello world!' and the message alerted is 'Hello world! cool'.
Property references allow us to get the value of the property of a component. This allows us to move across components. For example, let's say you have an Inputbox
component and you want to alert
the value of the input box whenever the user presses the Enter
button. How would we do that? Let's explore.
Let's start by taking a look at the following code:
[
{
"name": "inputbox1",
"component": "Inputbox",
"sections": []
"events": {
"onEnter": [
{
fn: "alert",
args: "Hello, var(inputbox1.value)!"
}
]
},
"props": {
"placeholder": "Enter your name..."
},
}
]
The above code will render an Inputbox
component with a placeholder of Enter your name...
. If we enter our name in the box and press the Enter
button on the keyboard an alert dialog is shown and var(inputbox1.value)
is replaced with the value of the input box.