JSFiddle - React, Tailwind, and code Playground
by lega911
HTML
<script src="https://angularlight.org/bin/alight_0.14.last.min.js"></script>
<h2>list navigator demo</h2>
<list-navigator :source="list" :initselected="::selected" @changed="selected=$value" :ctx="this">
<div class="item-container" :class.item-container-selected="selected[i.id]">
<div class="item-header" :class.item-header-archived="i.archived">
{{i.firstName}} {{i.lastName}}
<button al-if="!i.archived" class="btn-arch" @click="ctx.onArchive(i)">Archive</button>
</div>
<div class="item-details">
Id: {{i.id}}, Email: {{i.email}}, Gender: <span class="item-details-gender-{{i.gender.toLowerCase()}}">{{i.gender}}</span>
</div>
</div>
</list-navigator>
<div>
Selected: {{getSelectedUsersText()}}
</div>
<template id="navigator-tpl">
<div al-repeat="i in toDisplay()">
<div class="cb-wrapper">
<input type="checkbox" al-model="selected[i.id]" @change="onSelectedChange()"/>
</div>
<div class="item-wrapper" :html="itemTpl"></div>
</div>
<div>
<button @click="onPrev()" :disabled="firstPage()">Prev</button>
<button @click="onNext()" :disabled="lastPage()">Next</button>
</div>
</template>
CSS
body {
font-family: 'Segoe UI', sans-serif;
}
span {
font-style: italic;
}
.item-container {
margin: 8px;
padding: 8px;
width: 450px;
border: 1px solid darkslategrey;
border-radius: 5px;
}
.item-header {
font-size: 1.3rem;
}
.item-container-selected .item-header {
font-weight: bold;
}
.item-details {
color: dimgrey;
font-size: 0.9rem;
}
.item-details-gender-male {
color: blue;
}
.item-details-gender-female {
color:deeppink;
}
.cb-wrapper {
display: inline-block;
}
.item-wrapper {
display: inline-block;
}
.item-header-archived{
color: lightgray;
}
.btn-arch{
background-color: white;
border: 2px solid lightgray;
float: right;
}
.btn-arch:hover{
border-color: 2px solid gray;
background-color: gainsboro;
}
Babel + JSX
alight.component('list-navigator', function(scope, element) {
scope.itemTpl = element.innerHTML;
scope.onSelectedChange = () => scope.$sendEvent('changed', scope.source.filter((i) => scope.selected[i.id]));
scope.selected = {};
var page = 0;
scope.onPrev = () => page--;
scope.onNext = () => page++;
scope.firstPage = () => page < 1;
scope.lastPage = () => page*5+5>=scope.source.length;
scope.toDisplay = () => scope.source.slice(page*5, page*5 + 5);
return {
templateId: 'navigator-tpl',
onStart: () => {
for(let i of scope.initselected)
scope.selected[i.id] = true;
}
}
});
var app = {
list: listOfUsers(),
selected: listOfUsers().slice(1, 3),
getSelectedUsersText: () => app.selected.map((i) => i.firstName + ' ' + i.lastName).join(','),
onArchive: (i) => i.archived = true
};
alight('body', app);
////////////////////////////////////////////////
function listOfUsers() {
return [{ "id": 1, "firstName": "Stephanie", "lastName": "Owens", "email": "sowens0@cmu.edu", "gender": "Female" }, { "id": 2, "firstName": "Stephen", "lastName": "Torres", "email": "storres1@cbc.ca", "gender": "Male" }, { "id": 3, "firstName": "Lillian", "lastName": "West", "email": "lwest2@jalbum.net", "gender": "Female" }, { "id": 4, "firstName": "Larry", "lastName": "Hill", "email": "lhill3@phpbb.com", "gender": "Male" }, { "id": 5, "firstName": "Patrick", "lastName": "Duncan", "email": "pduncan4@prlog.org", "gender": "Male" }, { "id": 6, "firstName": "Steven", "lastName": "Nguyen", "email": "snguyen5@meetup.com", "gender": "Male" }, { "id": 7, "firstName": "Eugene", "lastName": "Garrett", "email": "egarrett6@psu.edu", "gender": "Male" }, { "id": 8, "firstName": "Juan", "lastName": "Wood", "email": "jwood7@elpais.com", "gender": "Male" }, { "id": 9, "firstName": "Harold", "lastName": "Little", "email": "hlittle8@walmart.com", "gender": "Male" }, { "id": 10, "firstName": "Linda", "lastName": "Cunningham", "email":...