component

A component in ftd is similar to “react component”. Components are independent and reusable bits of code. components have “arguments”, these are the data that must be passed to them, and using components we construct the user interface.

Create Your First Component

New components are defined using the component keyword followed by component name:
Creating a component named heading
-- component heading:

-- ftd.text: My Heading
color: red

-- end: heading
Lang:
ftd
Here, we have defined a new component heading. This component is using ftd.text, a kernel component, as a definition. We have created a custom-component which shows given text in red color.

Kernel Components

So, how is ftd.text implemented? ftd comes with some “kernel components”, these are the lowest level components that every other component uses directly or indirectly.

Read about our kernel components guide to learn about these components.

Rendering a Component

Till now, we have created a component called heading. Now to invoke or render this component in your ftd application, we can do the following:
Input
-- heading:
Lang:
ftd
Output
My Heading
Currently, My Heading is fixed text displayed by heading component. We can make it customisable by using attributes.

Rendering a Component Conditionally

We can render a component conditionally. This can be achieved using an if keyword.
Input
-- integer num: 10

-- heading:
if: { num <= 10 }
Lang:
ftd
Output
My Heading
Input
-- integer num: 10

-- heading:
if: { num > 10 }

-- ftd.text: Heading not shown!!
Lang:
ftd
Output
Heading not shown!!

Component Arguments

Component “arguments” refer to the inputs that are passed into a component when it is called or invoked. These arguments provide the component with the necessary data that is helpful to configure or customize the component’s behavior or appearance.

Component arguments are like function arguments, and you send them into the component as attributes.

The arguments in ftd components creates variables for each component invocation. These variables have local scope. This means that these variables can be accessed only inside the component definition in which they are declared.

Defining Component Arguments

Component arguments starts with argument type follow by argument name, in our component we can define one such argument, title.

The type of our title argument is string.
Using the title argument in the component
-- component heading:
string title:

-- ftd.text: $heading.title
color: red

-- end: heading
Lang:
ftd

Adding Attributes to Component

When the component is used in another component or in the main application, the title can be passed in as an attribute of the component:
Input
-- heading:
title: I love `ftd`!
Lang:
ftd
Output
I love ftd!

Using Specially Typed Arguments

We can use special types like caption, body or caption or body that give us flexibility to pass attributes in different location of ftd::p1 “section”.

Let’s use caption or body type using which we can pass attributes in either caption or body area.
caption or body type for title argument
-- component heading:
caption or body title:

-- ftd.text: $heading.title
color: red

-- end: heading
Lang:
ftd

Passing Attribute in Caption

Passing attribute in caption area makes the component more concise and readable. It also make it clear what the component represents and what its purpose is.
Input
-- heading: I am in caption area.
Lang:
ftd
Output
I am in caption area.

Passing Attribute in Body

Passing attributes in the body area can help make it more readable by providing a way to break up complex or lengthy inputs into more manageable chunks of text.
Input
-- heading:

I am in body area.

Since I am long description, it's better to pass it here. Isn't it?
Lang:
ftd
Output

I am in body area.

Since I am long description, it’s better to pass it here. Isn’t it?
ℹ️
Special types
By default caption or body is alias for string but if you want to pass types other than string you can do the following:
Input
-- component show-number:
caption integer number:

-- ftd.integer: $show-number.number

-- end: show-number

-- show-number: 45
Lang:
ftd
Output
45

Arguments with Default Values

An argument can be defined with a default value:
-- component heading:
caption or body title:
ftd.color text-color: red

-- ftd.text: $heading.title
color: $heading.text-color

-- end: heading
Lang:
ftd
If no argument is provided, the component instance adopts the default value of text-color defined by the heading. On the other hand, if an argument is provided, it supersedes the default value.
heading with default text-color
Input
--  heading: hello
Lang:
ftd
Output
hello
heading with text-color value as green
Input
-- heading: this is nice
text-color: green
Lang:
ftd
Output
this is nice

Global Variable Reference As Default Value

We can pass global variable reference as a default value:
Passing global variable reference ftd-title
-- string ftd-title: I love `ftd`!

-- component heading:
caption or body title: $ftd-title
ftd.color text-color: red

-- ftd.text: $heading.title
color: $heading.text-color

-- end: heading
Lang:
ftd
Input
-- heading:
Lang:
ftd
Output
I love ftd!

Other Argument Reference As Default Value

We can pass other argument reference as a default value:
-- component heading-with-detail:
caption title:
body detail: $heading-with-detail.title

-- ftd.column:
spacing.fixed.px: 20
color: $inherited.colors.text

-- ftd.text: $heading-with-detail.title
role: $inherited.types.heading-small

-- ftd.text: $heading-with-detail.detail
role: $inherited.types.label-small

-- end: ftd.column

-- end: heading-with-detail
Lang:
ftd
Input
-- heading-with-detail: Title same as detail
Lang:
ftd
Output
Title same as detail
Title same as detail

Conditional Attributes

Sometimes we want to set an attribute based on a condition.
True Condition Expression
Input
-- integer num: 10

-- heading:
title if { num <= 10 }: `num` is less than equal to 10
title: Default Title
Lang:
ftd
Output
num is less than equal to 10
False Condition Expression
Input
-- heading:
title if { num > 10 }: `num` is less than equal to 10
title: Default Title
Lang:
ftd
Output
Default Title

Creating Container Component

ftd provides some container type kernel component like ftd.row and ftd.column. The container component accepts the components as an attribute.

Using ftd.ui list type

We can define such arguments using ftd.ui list type.
-- component show-ui:
caption title:
ftd.ui list uis:

-- ftd.column:
spacing.fixed.px: 10
color: $inherited.colors.text

-- ftd.text: $show-ui.title

-- ftd.column:
children: $show-ui.uis
border-width.px: 1
padding.px: 10
border-color: $inherited.colors.border

-- end: ftd.column

-- end: ftd.column

-- end: show-ui
Lang:
ftd
Here, we have defined an argument uis of type ftd.ui list. We have also pass this to children attribute of ftd.column.
Input
-- show-ui: My UIs

-- show-ui.uis:

-- ftd.text: My First UI
-- heading: Using Heading Too

-- end: show-ui.uis
Lang:
ftd
Output
My UIs
My First UI
Using Heading Too

Using children type

The children type allows us to pass components in subsection location.
-- component show-ui:
caption title:
children uis:

-- ftd.column:
spacing.fixed.px: 10
color: $inherited.colors.text

-- ftd.text: $show-ui.title

-- ftd.column:
children: $show-ui.uis
border-width.px: 1
padding.px: 10
border-color: $inherited.colors.border

-- end: ftd.column

-- end: ftd.column

-- end: show-ui
Lang:
ftd
Input
-- show-ui: My UIs

-- ftd.text: My First UI
-- heading: Using Heading Too

-- end: show-ui
Lang:
ftd
Output
My UIs
My First UI
Using Heading Too

Mutable Component Arguments

In ftd, we can define a component argument as mutable by using the $ prefix before its name. A mutable argument can be modified within the component and can take mutable variables as input, which can be modified outside the component’s scope too. Any changes made to a mutable argument will be reflected in the component’s output.

Consider the following code snippet:
-- component toggle-ui:
caption title:
body description:
boolean $open: true

-- ftd.column:

-- ftd.text: $toggle-ui.title

-- ftd.text: $toggle-ui.description
if: { toggle-ui.open }

-- end: ftd.column

-- end: toggle-ui
Lang:
ftd
In the above example, the $open argument is mutable, which means it can be modified both within and outside the toggle-ui component. Any changes made to the $open argument will be immediately reflected in the component’s output.
Input
-- toggle-ui: My Title
$open: false

My Description
Lang:
ftd
Output
My Title
Input
-- toggle-ui: My Title

My Description
Lang:
ftd
Output
My Title
My Description

Passing Mutable Variable to Mutable Argument

Consider the following code snippet:
-- boolean $global-open: true

-- ftd.text: I change global-open
$on-click$: $ftd.toggle($a = $global-open)

-- toggle-ui: My Title
$open: $global-open

My Description
Lang:
ftd

We have added an $on-click$ event here and used ftd built-in function ftd.toggle. The function toggles the boolean value whenever event occurs.

We have passed mutable reference of global-open to open attribute. So the change in global-open value changes the open attribute too.
Click on the I change global-open and see the effect.
I change global-open
My Title
My Description

Events in Component

We have created toggle-ui component, now lets add event to this.
-- component toggle-ui:
caption title:
body description:
boolean $open: true

-- ftd.column:
$on-click$: $ftd.toggle($a = $toggle-ui.open)

-- ftd.text: $toggle-ui.title

-- ftd.text: $toggle-ui.description
if: { toggle-ui.open }

-- end: ftd.column

-- end: toggle-ui
Lang:
ftd
We have added an $on-click$ event and ftd.toggle action in ftd.column component and pass toggle-ui.open argument.
Click on the rendered component below and see the effect.
Input
-- toggle-ui: Click me!

My Description
Lang:
ftd
Output
Click me!
My Description

Support fastn!

Enjoying fastn? Please consider giving us a star ⭐️ on GitHub to show your support!

Getting Help

Have a question or need help?

Visit our GitHub Q&A discussion to get answers and subscribe to it to stay tuned.

Join our Discord channel and share your thoughts, suggestion, question etc.

Connect with our community!

Found an issue?

If you find some issue, please visit our GitHub issues to tell us about it.

Join us

We welcome you to join our Discord community today.

We are trying to create the language for human beings and we do not believe it would be possible without your support. We would love to hear from you.
Copyright © 2023 - FifthTry.com