JavaScript List
Pico Library
This library has less than 2 KBytes
The LemonadeJS List is a library to create elements with search and pagination. It helps transform an array of objects into a list of HTML elements based on a defined template. It brings search and pagination natively, and it is possible to bind extended methods to extend its features.
Documentation
Installation
npm install @lemonadejs/list
Attributes
Attribute | Description |
---|---|
data: Array<Object> | Data should be an array of objects. |
pagination?: Number | Enable the pagination and define the number of items per page. |
search?: Boolean | Enable the search. |
onsearch?: Function | When a search happens. |
onchangepage?: Function | When the user changes the page. |
Important points
- Reserved self properties: This library will create a item for each position of the data array. Each item will have its own self and a few reserved properties such as
self.el
andself.parent
.- Template: The content of the component <List>
all code here
</List> is the template which will serve to create the items from the list. It is important you have only one root element.- React/Vue Template: In both React and Vue, it is essential to pass the template as a property. This requirement arises from the necessity for Lemonade to render the template in the component. Exploration of this necessity is detailed in the examples below.
Examples
Basic example
Create quick reactive javascript lists with search and pagination.
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/list/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/list/dist/style.min.css"/>
<div id='root' class="cards"></div>
<script>
function Component() {
const self = this;
self.rows = [
{ name:"bulbasaur", id: 1 },
{ name:"ivysaur", id: 2 },
{ name:"venusaur", id: 3 },
{ name:"charmander", id: 4 },
{ name:"charmeleon", id: 5 },
{ name:"charizard", id: 6 },
{ name:"squirtle", id: 7 },
{ name:"wartortle", id: 8 },
{ name:"blastoise", id: 9 },
{ name:"caterpie", id: 10 },
];
return `<>
<List :data="self.rows" :search="true" :pagination="5">
<div class="card">
<img src="/templates/default/img/pokemon/{{self.id}}.svg" />
<div>{{self.name}}</div>
</div>
</List>
</>`;
}
// Render component
lemonade.render(Component, document.getElementById('root'));
</script>
</html>
import lemonade from "lemonadejs";
import List from "@lemonadejs/list";
import "@lemonadejs/list/dist/style.css";
import "./style.css"; // The CSS file should incorporate the CSS provided beneath this example.
export default function Component() {
const self = this;
self.rows = [
{ name:"bulbasaur", id: 1 },
{ name:"ivysaur", id: 2 },
{ name:"venusaur", id: 3 },
{ name:"charmander", id: 4 },
{ name:"charmeleon", id: 5 },
{ name:"charizard", id: 6 },
{ name:"squirtle", id: 7 },
{ name:"wartortle", id: 8 },
{ name:"blastoise", id: 9 },
{ name:"caterpie", id: 10 },
];
return `<>
<List :data="self.rows" :search="true" :pagination="5">
<div class="card">
<img src="https://lemonadejs.com/templates/default/img/pokemon/{{self.id}}.svg" />
<div>{{self.name}}</div>
</div>
</List>
</>`;
}
import React, { useRef } from "react";
import List from "@lemonadejs/list/dist/react";
import "@lemonadejs/list/dist/style.css";
export default function Component() {
const component = useRef();
const rows = [
{ name:"bulbasaur", id: 1 },
{ name:"ivysaur", id: 2 },
{ name:"venusaur", id: 3 },
{ name:"charmander", id: 4 },
{ name:"charmeleon", id: 5 },
{ name:"charizard", id: 6 },
{ name:"squirtle", id: 7 },
{ name:"wartortle", id: 8 },
{ name:"blastoise", id: 9 },
{ name:"caterpie", id: 10 },
]
const template = `<div class="card">
<img src="/templates/default/img/pokemon/{{self.id}}.svg" />
<div>{{self.name}}</div>
</div>`
return (<div>
<List ref={component} data={rows} search={true} pagination={5} template={template} />
</div>)
}
<template>
<List :ref="component" :data="rows" :pagination="5" :search="true" :template="template" />
</template>
<script>
import List from '@lemonadejs/list/dist/vue';
import '@lemonadejs/list/dist/style.css';
export default {
name: 'App',
components: {
List,
},
data() {
const rows = [
{ name:"bulbasaur", id: 1 },
{ name:"ivysaur", id: 2 },
{ name:"venusaur", id: 3 },
{ name:"charmander", id: 4 },
{ name:"charmeleon", id: 5 },
{ name:"charizard", id: 6 },
{ name:"squirtle", id: 7 },
{ name:"wartortle", id: 8 },
{ name:"blastoise", id: 9 },
{ name:"caterpie", id: 10 },
];
const template = `<div class="card">
<img src="/templates/default/img/pokemon/{{self.id}}.svg" />
<div>{{self.name}}</div>
</div>`;
return {
rows,
template
}
}
};
</script>
Example with operations
The next example implements two operations on the array of objects.
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/list/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/list/dist/style.min.css" />
<div id='root'></div>
<script>
// Create basic component
const Countries = function() {
const self = this;
self.countries = [
{ "name": "Australia" },
{ "name": "Austria" },
{ "name": "Chile" },
];
self.add = function() {
// Add the country
self.countries.push({ name: self.name.value });
// Refresh the array
self.refresh('countries');
}
self.delete = function(_, s) {
// Find and delete the position based on the self given
self.countries.splice(self.countries.indexOf(s), 1);
// Refresh the array
self.refresh('countries');
}
return `<>
<List :data="self.countries" search="false">
<div class="p4">
<span style="width: 200px; display: inline-block">{{self.name}}</span>
<input type="button" onclick="self.parent.parent.delete" value="Delete" style="width: 80px;" />
</div>
</List>
<div class="p4">
<input type="text" :ref="self.name" placeholder="Add new item" style="width: 200px;" />
<input type="button" value="Add" onclick="self.add" style="width: 80px;" />
</div>
</>`;
}
lemonade.render(Countries, document.getElementById('root'));
</script>
</html>
export default function() {
const self = this;
self.countries = [
{ "name": "Australia" },
{ "name": "Austria" },
{ "name": "Chile" },
];
self.add = function() {
// Add the country
self.countries.push({ name: self.name.value });
// Refresh the array
self.refresh('countries');
}
self.delete = function(_, s) {
// Find and delete the position based on the self given
self.countries.splice(self.countries.indexOf(s), 1);
// Refresh the array
self.refresh('countries');
}
return `<>
<List :data="self.countries" search="false">
<div class="p4">
<span style="width: 200px; display: inline-block">{{self.name}}</span>
<input type="button" onclick="self.parent.parent.delete" value="Delete" style="width: 80px;" />
</div>
</List>
<div class="p4">
<input type="text" :ref="self.name" placeholder="Add new item" style="width: 200px;" />
<input type="button" value="Add" onclick="self.add" style="width: 80px;" />
</div>
</>`;
}
import React, { useRef, useEffect, useState } from "react";
import List from "@lemonadejs/list/dist/react";
import "@lemonadejs/list/dist/style.css";
const rows = [
{ "name": "Australia" },
{ "name": "Austria" },
{ "name": "Chile" },
];
export default function Component() {
const component = useRef();
const name = useRef();
const [data, setData] = useState(rows);
let d = data
const template = `<div class="p4">
<span style="width: 200px; display: inline-block">{{self.name}}</span>
<input type="button" onclick="self.parent.delete" value="Delete" style="width: 80px;" />
</div>`
const add = function () {
d = [...data, { name: name.current.value }]
setData(d)
}
useEffect(() => {
if (component.current) {
component.current.delete = function (_, s) {
let i = d.indexOf(s)
d = d.slice(0, i).concat(d.slice(i + 1))
setData(d)
}
}
})
return (<div>
<List ref={component} data={data} search={false} template={template} />
<div className="p4">
<input type="text" ref={name} placeholder="Add new item" style={{width: '200px'}} />
<input type="button" value="Add" onClick={add} style={{width: '80px'}} />
</div>
</div>)
}
<template>
<List ref="component" :data="countries" :search="false" :template="template" />
<div class="p4">
<input type="text" ref="name" placeholder="Add new item" style="width: 200px;" />
<input type="button" value="Add" @click="add" style="width: 80px;" />
</div>
</template>
<script>
import List from '@lemonadejs/list/dist/vue';
import '@lemonadejs/list/dist/style.css';
export default {
name: 'App',
components: {
List,
},
data() {
const countries = [
{ "name": "Australia" },
{ "name": "Austria" },
{ "name": "Chile" },
];
const template = `<div class="p4">
<span style="width: 200px; display: inline-block">{{self.name}}</span>
<input type="button" onclick="self.parent.delete" value="Delete" style="width: 80px;" />
</div>`;
return {
countries,
template
}
},
mounted() {
const self = this;
this.$refs.component.current.delete = function (_, s) {
let i = self.countries.indexOf(s)
self.countries = self.countries.slice(0, i).concat(self.countries.slice(i + 1));
}
},
methods: {
add: function () {
this.countries = [...this.countries, { name: this.$refs.name.value }];
}
}
};
</script>
Custom CSS for this example
.cards .list-content {
display: flex;
max-width: 600px;
}
.card {
width: 80px;
height: 80px;
margin: 5px;
text-align: center;
font-size: 0.8em
}
.card img {
width: 40px;
height: 40px;
object-fit: contain;
}