Deprecated: This component is deprecated and will not receive any updates. Please use kami-collection instead.
An infinite scroller. Just add a datasource provider and a delegate web components and it's work !
npm install --save kami-infinitelist
Or use the CDN :
<script src="https://cdn.jsdelivr.net/npm/kami-infinitelist"></script>
<script src="https://cdn.jsdelivr.net/npm/kami-infinitelist"></script>
<script>
window.onload = function(){
customElements.define('kami-infinitelist', KamiInfiniteList);
}
</script>
Or with webpack / rollup
// ES6 Modules or TypeScript
import KamiInfiniteList from 'kami-infinitelist'
// register the component with the name you want
window.customElements.define('kami-infinitelist', KamiInfiniteList);
For use the infinite list you need two prerequire.
- a datasource
- a delegate
The datasource should be an JSON endpoint with query pagination. For exemple see the jsonplaceholder api work as well. Into the request, the component will add a query with some paramters :
- page : the number of the current page
- limit : the number of item by page
You can update the param name with the properties pageQuery and limiQuery. For more information see the Props section.
The delegate should be a web component. The property of this component will be map to the data by the infinte list component.
This component should be into the main slot of the list. For more information see the Data Binding section.
This the source code to create a simple list with this component. This is the final result.
index.html
<!-- infinite list component -->
<kami-infinitelist
datasource="https://jsonplaceholder.typicode.com/posts/"
delegate="post-custom"
limitQuery="_limit"
pageQuery="_start"
limit='22'
width="700px"
>
<!-- delegate component -->
<post-custom
titleprops="title"
bodyprops="body"
>
</post-custom>
</kami-infinitelist>
<!-- import iron icon if necessary -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@polymer/[email protected]/iron-icons.min.js"></script>
<!-- infinite list lib -->
<script src="./KamiInfiniteList.umd.js"></script>
<!-- base component lib -->
<script src="./KamiComponent.umd.js"></script>
<!-- delegate component lib -->
<script src="./Post.js"></script>
<script>
window.onload = function(){
//init component
customElements.define('post-custom',Post);
customElements.define('kami-infinitelist', KamiInfiniteList);
}
</script>
Post.js
class Post extends KamiComponent
{
constructor()
{
super();
}
static get observedAttributes() {
return [
'titleprops',
'bodyprops',
];
}
//set your properties to the parent
//necessary for the render() method
setProperties()
{
this.props = this.observe({
titleprops: this.getAttribute('titleprops'),
bodyprops: this.getAttribute('bodyprops')
})
}
//init all your event listener
initEventListener()
{
this.wrapper.querySelector('.post').addEventListener('click',()=>{
alert(`title: ${this.props.titleprops} body: ${this.props.bodyprops}`)
})
}
connectedCallback()
{
this.observeWindows = new IntersectionObserver(this.display.bind(this),{
root: null,
rootMargin: '0px',
threshold: 0.1
});
this.observeWindows.observe(this)
this.wrapper.style.position = 'relative';
}
display(changes)
{
changes.forEach(change => {
if (change.intersectionRatio > 0) {
this.wrapper.querySelector('.post').classList.add('post--display');
}
});
}
//render the dom structure
renderHtml()
{
return `
<div class="post">
<div class="post__title">${this.props.titleprops}</div>
<div class="post__body">${this.props.bodyprops}</div>
</div>
`;
}
//render the style component
renderStyle()
{
return `
.post{
margin: 5px;
padding: 5px;
background-color: ghostwhite;
font-family: sans-serif;
cursor: pointer;
transform: translateY(20px);
opacity: 0;
transition: all 1s ease;
}
.post--display{
transform: translateY(0px);
opacity: 1;
transition: all 1s ease;
}
.post:hover{
color: white;
background-color: grey;
}
.post__title{
font-size: 20px;
margin: 5px 0px;
}
.post__title:first-letter{
text-transform: capitalize;
}
`;
}
}
To bind data to the infinite list you should create a delegate component. Schema of the data should be write into the delegate props.
For example we have this data :
[
{
"username": "test",
"fullname": {
"firstname": "test",
"lastname": "test"
},
"posts": [
{
"title": "post1",
"content":"content1"
},
{
"title": "post2",
"content":"content2"
},
]
}
]
To bind this you can create a user component :
<!-- infinite list component -->
<kami-infinitelist
delegate="user-element"
otherProps...
>
<!-- delegate component -->
<user-element
username="username"
firstname="fullname.firstname"
lastname="fullname.lastname"
posts="posts"
>
</user-element>
</kami-infinitelist>
To bind array the component will stringify your data. You should to parse manually into your delegate like this :
// try catch are necessary if your delegate component extends KamiComponent.
try {
return JSON.parse(this.getAttribute('posts'));
} catch (error) {
return [];
}
See also the issues example for more details.
If your request response with an object and your data to bind are into a nested field. You can use the nested
prop to bind this field and not the root object.
{
info: {
status: 200
},
// nested field
results: [
{
"username": "test",
"fullname": {
"firstname": "test",
"lastname": "test"
},
"posts": [
{
"title": "post1",
"content":"content1"
},
{
"title": "post2",
"content":"content2"
},
]
}
]
}
<!-- infinite list component -->
<kami-infinitelist
nested="results"
otherProps...
>
<!-- delegate component -->
</kami-infinitelist>
See also the nested example for more details.
Kami-infinitlist use iron-icons for display icons. If you want use this icone you need to import it manually.
npm install --save @polymer/iron-icons
<!-- import iron icon if necessary -->
<script type="module">
import './node_modules/@polymer/iron-icon/iron-icon.js';
import './node_modules/@polymer/iron-icons/iron-icons.js';
</script>
<!-- import before import kami infinite list -->
<script src="./KamiInfiniteList.umd.js"></script>
Or with webpack / rollup
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/iron-icons/iron-icons.js';
// import before init kami infinite list
import KamiInfiniteList from 'kami-infinitelist'
See also search example into the example folder.
name | type | description | required | default value |
---|---|---|---|---|
datasource | String | Datasource provider | true | |
delegate | String | Delegate web component | true | |
width | String | Width of the list | false | 100% |
height | String | Height of the list | false | 100vh |
useSearch | Boolean | Diplay the search bar | false | false |
searchQuery | String | Name of the search param in the query | false | search |
sortQuery | String | Name of the sort param in the query | false | sort |
pageQuery | String | Name of the page param in the query | false | page |
limitQuery | String | Name of the limit param in the query | false | limit |
page | Number | Number of the current page | false | 1 |
limit | Number | Number of item display | false | 10 |
flex | Boolean | Use the flex property | false | false |
nested | string | Parse an array into a nested field see the data binding section | false | null |
name | trigger | event.detail |
---|---|---|
clickElement | When a element of the list is clicked | { element: HTMLElement, index: number } |
We would love you for the contribution to kami-infinitelist
project, check the CONTRIBUTING
file for more info.