This page offers a quick overview of the language together with some examples.
Live Elements files end with the .lv
extension. lv
files support both javascript and live elements code, the only restriction is that lv
files can only export components or component instances. Live elements code is used only for declaring and creating components, everything else inside components, like functions, property assignments, event listeners and other type of logic is written in javascript.
component X{
fn printX(){ // a function with js code
console.log('This is component X')
}
// a function assigned to a property
y : () => { console.log('Called X property y') }
}
Live Elements files are grouped into modules, and one or more modules forms a package. A module in Live elements is a folder with one or more lv
files. All exports from .lv
files are available to each other inside the same folder. For example, if A.lv
and B.lv
are in the same folder, and A.lv
exports component A, in B.lv
we can access A directly:
A.lv
file:
component A{}
B.lv
file:
component B{
fn getA(){ return A } // return component A
}
To access components outside the folder we're in, we need to import that folder. Imports can be of 2 types: relative, and absolute. Relative imports start with a dot (.
), and they import from the same package. Absolute imports start with the package name:
// relative import
import .a // : will import module 'a' from the root of the current package
// absolute import
import live-web.dom // will import 'dom' module from 'live-dom' package
Note:
You can experiment with these concepts inside the playground, which you can install locally:
npm i live-elements-web-cli
npx lvweb init --template playground
npx lvweb serve
The playground should be running on localhost:8080. In the top left corner, click on the Open icon, and select: Console: Application
The following application provides a run function where you can experiment with live elements and javascript code: If you're having trouble setting it up, you can checkout the quick-start-language section for more information.
Components are similar to javascript classes, but with extra functionality. A component is declared like this:
component X{}
A component that inherits another component is declared using this <
symbol:
component Y < X{}
All components inherit from BaseElement
, similarly to how all classes in javascript inherit from the Object
class.
To create a component, use curly braces after the component name:
let a = X{}
let b = Y{}
Components declare properties like this:
component Point{
number x: 0
number y: 0
}
Properties can be declared without assignning them:
component Point{
number x
number y
}.
Properties can be assigned when inheriting a component that declared a property:
component OriginPoint < Point{
x: 0
y: 0
}
They can also be assigned when creating a new component instance:
const a = Point{
x: 10
y: 10
}
Properties automatically bind to properties they're assigned to:
const a = Point{
x: 10
y: this.x // x is now bound to y
}
console.log(a.y) // 10
a.x = 20
console.log(a.y) // 20, as x is now 20 and y is bound to x
To avoid bindings, the equal sign can be used intead of the colon:
const a = Point{
x : 10
y = this.x // will not bind y to x
}
a.x = 20
console.log(a.y) // 10
Constructors use the constructor
keyword:
component Point{
number x
number y
constructor(x:number, y:number){
super()
this{ x = x; y = y }
}
}
All constructor arguments must be succeeded by a type. All types are typescript types. Whithin the constructor body, the call to super()
is required and this{}
initializer is also required and can be used to initialize declared properties: this{ x = value; y = value }
.
The following notation is used to create such a component:
const point = Point.(10, 10){}
Quick text constructors are shortcuts to initialize a component with a single string constructor:
component Text{
string data
constructor(data:string){
data()
this{ data = data }
}
}
const t = Text`Welcome` Same as Text.('Welcome'){}
Lines are concatenated into a single one, and spaces are trimmed:
const t = Text`
this text spans on
multiple lines, but
will be merged into one
`
Tripple backticks can be used to preserve spaces and new lines:
const t = Text```
This text will actually be on
multiple lines
```
Components can accept children by declaring the default children
property:
component TreeNode{
default children
}
const hierarchy = TreeNode{
TreeNode{}
TreeNode{
TreeNode{}
TreeNode{}
}
}
Inside hierarchies, component instances can be accessed using an id:
component TreeNode{
default children
string data
}
const hierarchy = TreeNode{
id: root // can now be accessed as root
data: 'shared-data'
TreeNode{
data: root.data // this will now be 'shared-data'
TreeNode{
data: root.data // this will also be data
}
}
}
Just like classes, components can have functions:
component A{
fn sayHello(){
console.log('hello')
}
}
const a = A{}
a.sayHello()
Argument types are required, while the return type is optional:
component A{
fn say(message:string){
console.log(message)
}
}
const a = A{}
a.say('hello')
Static functions use the static
keyword:
compoent A{
static fn say(message:string){
console.log(message)
}
}
A.say('hello')
Components can declare events. Events can be triggered using the emit
function:
component A{
event event1()
event event2(x:number, y:number)
fn triggerEvent1(){
this.event1.emit()
}
fn triggerEvent2(){
this.event2.emit(10, 20)
}
}
Listeners assign a function to be executed when an event was triggered:
component A{
event event1()
event event2(x:number, y:number)
on event1: () => {
console.log("Event 1 triggered")
}
on event2: (x, y) => {
console.log("Event 2 triggered with: x=" + x + " and y=" + y)
}
}
All properties automatically add an event named <property_name>Changed
, which is triggered when the property changes:
component A{
number x: 0
on xChanged: () => {
console.log("x changed to " + this.x)
}
}
const a = A{}
a.x = 10 // will log: x changed to 10
Events and listeners can be declared when creating a component as well:
const a = A{
event event1()
on event1: () => { console.log('Event 1 triggered') }
}
The following 4 pages cover all the language features in depth: