This article is a step by step guide to create a simple web app using Live Elements.
To get up and running fast, we're going to use lvweb
to generate a starting project template. lvweb
is a tool found in live-elements-web-cli
package, which can be installed using npm
, either locally, in a new folder:
npm i live-elements-web-cli
Or globally:
npm i -g live-elements-web-cli
Note: The installation page offers more information if you have trouble installing lvweb or want other options.
In this guide we're going to use lvweb locally, so we will start by creating an empty folder for the project:
mkdir quickstart
cd quickstart
Then we install lvweb, and use it to initialize a new project:
npm i live-elements-web-cli
lvweb init
This will generate a package.json
file with all of the dependencies, together with all the source files needed for the initial project. We will need to install the dependencies in the generated package.json
:
npm i
And run the project:
lvweb serve
Now, navigating with a browser to http://localhost:8080, we should see the following message:
Welcome to Live Elements
To understand what's happening behind the scenes, we first need to look at the project structure.
The following structure has been setup by lvweb
:
|-- live.package.json
|-- package.json
|-- app
| |-- Home.lv
|-- bundle
| |-- bundle.lv
|-- styles
| |-- style.css
Within the root, there are 2 files:
live.package.json
describes a live elements package. It includes the name and version of this package.package.json
is the npm file that describes this package. It has been configured with the name of the folder, and initialized with all the required dependencies to run this projectAnd 4 folders:
app
contains files for the front-end application run on the client side.bundle
contains the bundle file interpreted by the server in order to create routes, manage assets, styles, and other things.styles
contains the css files for the application.build
is generated by the live elements compiler, and contains all the compiled .lv files.This is the file that renders the index page:
import live-web.dom
import live-elements-web-server.view
component Home < PageView{
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
H1`Welcome to Live Elements!`
}
The file defines the Home
component, inheriting from PageView
:
component Home < PageView{}
The head property manages the page <head>
section. This is where we set the title of the page, and add a style link:
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
The content is a simple heading, equivalent to the html code:
<h1>Welcome to Live Elements!</h1>
This is the file run by the server:
import live-elements-web-server.bundle
import live-elements-web-server.router
import live-elements-web-server.style
import .app
instance bundle Bundle{
ViewRoute{ url: '/' c: Home }
Stylesheet{ src: './styles/style.css' output: 'style.css' }
}
The file exports a bundle object, with the following 2 elements:
ViewRoute
sets up the Home
component at the index /
route.Home
is imported from the app folder, using the import: import .app
. Imports in Live Elements from the same package start with the dot (.
) notation.Stylesheet
defines a source style in ./styles/style.css
. The path is relative from the root of the package. The output property sets the name of the style to be made available inside the styles
route. Since the output is style.css
, the style will be available at /styles/style.css
.For this guide, we won't need to configure anything on the server side, so we will go back to the Home
file.
Let's start by adding a paragraph to our homepage. In html, this would be the <p>
tag, which is equivalent to P
in Live Elements. The PageView
allows only a single root element, so we will have to explicitly define Body
this time:
import live-web.dom
import live-elements-web-server.view
component Home < PageView{
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
Body{
H1`Welcome to Live Elements!`
P`This is a paragraph.`
}
}
If lvweb serve
is running, the page should refresh automatically after saving the file. Otherwise, you will have to start lvweb again.
You might not see any changes when reloading the page, and that's because of the used stylesheet. Since we will be creating a new application, we can remove everything in the style/style.css
file, and just leave a simple body:
body{
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
color: black;
margin: 0px;
padding: 0px;
}
The paragraph should now be visible.
To make things more interactive, let's add a button:
import live-web.dom
import live-elements-web-server.view
component Home < PageView{
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
Body{
H1`Welcome to Live Elements!`
P`This is a paragraph.`
Button{ T`Clickable` }
}
}
We can alert a message when the button is clicked using the on click
event:
import live-web.dom
import live-elements-web-server.view
component Home < PageView{
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
Body{
H1`Welcome to Live Elements!`
P`This is a paragraph.`
Button{
on click: () => { alert('Button clicked.') }
T`Clickable`
}
}
}
To interact with other elements, we can reference them using their id
. In the example below, the paragraph has a background color, which will change once the button is clicked:
import live-web.dom
import live-elements-web-server.view
component Home < PageView{
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
Body{
H1`Welcome to Live Elements!`
P{
id: paragraph
style = { backgroundColor: 'green' }
T`This is a paragraph.`
}
Button{
on click: () => { paragraph.style = { backgroundColor: 'red' } }
T`Clickable`
}
}
}
From the changes we made so far, it's quite easy to go for something more practical, like the classical todo list:
import live-web.dom
import live-elements-web-server.view
component Home < PageView{
head: PageProperties{
title: "Live Elements"
StyleLink{ href: '/styles/style.css' }
}
Body{
Ul{
id: todoList
Li{
T`Buy Groceries`
Button{
on click: () => { todoList.children = todoList.children.filter(v => v != this.parent) }
T`x`
}
}
Li{
T`Visit North Pole`
Button{
on click: () => { todoList.children = todoList.children.filter(v => v != this.parent) };
T`x`
}
}
}
P{
Input{ id: newItem; type: 'text'; value: '' }
Button{
on click: () => {
let li = Li{
T.(newItem.currentValue){}
Button{
on click: () => { todoList.children = todoList.children.filter(v => v != this.parent) }
T`x`
}
}
todoList.children = todoList.children.concat([li])
newItem.value = ''
}
T`+`
}
}
}
}
We've used Ul
and Li
, which get converted into the html <ul>
and <li>
tags. For each Li
, or list item, there's a delete button, that removes the item from the list when clicked.
Below the list, theres an input
and a button
, which will create create a new list item from the value inside Input.
The list items in the code can be wrapped by a component to not repeat the same structure throghout the list. The component will need a label
property, which is the value to be displayed in the list.
import live-web
import live-web.dom
component TodoListItem < Li{
id: todoListItem
string label: ''
T{ text: parent.label }
Button{
on click: () => {
todoListItem.parent.children = todoListItem.parent.children.filter(v => v != todoListItem)
};
T`x`
}
}
instance app Application{
render: Div{
Ul{
id: todoList
TodoListItem{ label: 'Buy Groceries' }
TodoListItem{ label: 'Visit North Pole' }
}
P{
Input{ id: newItem; type: 'text'; value: '' }
Button{
on click: () => {
let value = newItem.currentValue
let li = TodoListItem{ label: value }
todoList.children = todoList.children.concat([li])
}
T`+`
}
}
}
}
TodoListItem
is a new component that declares a label property. It inherits from Li
, so everywhere it's created, it will create the Li
tag. It has 2 children, a text (T
) node, and a button (Button
) node. When the Button
is clicked, it will delete the current item from the Li
parent.TodoListItem
is then reused by creating the object, and assigning a label: TodoListItem{ label: 'Item Label' }
.
To wrap up, we're going to apply the following styles to our todolist:
body{
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
color: black;
margin: 0px;
padding: 0px;
}
ul{
list-style-type: none;
max-width: 400px;
margin: 100px auto 10px auto;
border: 1px solid #ccc;
border-radius: 20px;
padding: 0px;
}
ul li{
border-bottom: 1px solid #ccc;
margin: 20px;
padding: 10px;
}
li button{
float: right;
}
p{
max-width: 400px;
height: 40px;
margin: 10px auto 10px auto;
border-radius: 10px;
border: 1px solid #ccc;
padding: 15px 0px;
}
p input{
margin-left: 15px;
width: 300px;
height: 25px;
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
}
p button{
height: 25px;
width: 25px;
float: right;
margin-right: 20px;
}
The style should apply once you save the file.
We now have a simple Live Elements application up and running. For more lessons, and a deeper dive into the language there are more tutorials available in the tutorials section.