{"id":20804376,"url":"https://github.com/mgnstudio7/stenciljs-virtual-scroll","last_synced_at":"2025-05-07T03:43:22.907Z","repository":{"id":57370776,"uuid":"117237650","full_name":"mgnstudio7/stenciljs-virtual-scroll","owner":"mgnstudio7","description":"Virtual Scroll Web Component with DIFFERENT element height","archived":false,"fork":false,"pushed_at":"2018-06-28T08:03:23.000Z","size":386,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-31T05:51:12.288Z","etag":null,"topics":["angular","angular5","angularx","ionic","javascript","react","react-native","scroll","stencil","stenciljs","typescript","virtual-scroll","web-components","webcomponents"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mgnstudio7.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-12T12:17:19.000Z","updated_at":"2022-07-19T11:06:15.000Z","dependencies_parsed_at":"2022-09-18T10:30:35.636Z","dependency_job_id":null,"html_url":"https://github.com/mgnstudio7/stenciljs-virtual-scroll","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgnstudio7%2Fstenciljs-virtual-scroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgnstudio7%2Fstenciljs-virtual-scroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgnstudio7%2Fstenciljs-virtual-scroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgnstudio7%2Fstenciljs-virtual-scroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mgnstudio7","download_url":"https://codeload.github.com/mgnstudio7/stenciljs-virtual-scroll/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250699402,"owners_count":21473219,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular5","angularx","ionic","javascript","react","react-native","scroll","stencil","stenciljs","typescript","virtual-scroll","web-components","webcomponents"],"created_at":"2024-11-17T19:09:05.590Z","updated_at":"2025-05-07T03:43:22.890Z","avatar_url":"https://github.com/mgnstudio7.png","language":"TypeScript","readme":"![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-16161d.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D\u0026colorA=16161d\u0026style=flat-square)\n\n# Stenciljs-virtual-scroll\n\nThis is a project for building a standalone Virtual Scroll Web Component using Stencil.\nProject contain collection of two components:\n\n**1.** virtual-scroll (VirtualScrollWebComponent).\nThis component render subset of elements with **DIFFERENT** height, required to fill the viewport\n\n**2.** fetch-helper (FetchHelperWebComponent)\nThis component show you, how to use virtual scroll without framework.\n\n\n## Get Started with Angular5 (Ionic 3)\n\n**Step 1.** Install Stenciljs-virtual-scroll\n\n```sh\nnpm install stenciljs-virtual-scroll --save\n```\n\n**Step 2.** Import virtual scroll component into your angular app module\n\n```ts\n....\nimport 'stenciljs-virtual-scroll/dist/virtualscroll';\n....\n\n```\n\n**Step 3.** Import CUSTOM_ELEMENTS_SCHEMA into your angular app module\n\n```ts\n....\nimport { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';\n....\n\n@NgModule({\n    ...\n    schemas: [ CUSTOM_ELEMENTS_SCHEMA ]\n    ....\n})\nexport class AppModule { }\n\n```\n\n**Step 4.** Copying the Components\n\nFor Angular2+\n\nDuring the build, the components need to be copied to the build output directory. The easiest way to do this is to modify include the collection in the assets array of the .angular-cli.json file.\n\n```json\n\"assets\": [\n        \"assets\",\n        \"favicon.ico\",\n        { \"glob\": \"**/*\", \"input\": \"../node_modules/stenciljs-virtual-scroll/dist/virtualscroll\", \"output\": \"./virtualscroll\" }\n      ]\n\n```\n\nFor Ionic2+\n\nYou must use app-script to copy web component files in www directory\n\n1. Add in package.json \n```json\n\"config\": {\n    \"ionic_copy\": \"./config/copy.config.js\"\n  }\n```\n\n2. Create config/copy.config.js and put in\n\n```ts\n// this is a custom dictionary to make it easy to extend/override\n// provide a name for an entry, it can be anything such as 'copyAssets' or 'copyFonts'\n// then provide an object with a `src` array of globs and a `dest` string\nmodule.exports = {\n    copyAssets: {\n      src: ['{{SRC}}/assets/**/*'],\n      dest: '{{WWW}}/assets'\n    },\n    copyIndexContent: {\n      src: ['{{SRC}}/index.html', '{{SRC}}/manifest.json', '{{SRC}}/service-worker.js'],\n      dest: '{{WWW}}'\n    },\n    copyFonts: {\n      src: ['{{ROOT}}/node_modules/ionicons/dist/fonts/**/*', '{{ROOT}}/node_modules/ionic-angular/fonts/**/*'],\n      dest: '{{WWW}}/assets/fonts'\n    },\n    copyPolyfills: {\n      src: [`{{ROOT}}/node_modules/ionic-angular/polyfills/${process.env.IONIC_POLYFILL_FILE_NAME}`],\n      dest: '{{BUILD}}'\n    },\n    copySwToolbox: {\n      src: ['{{ROOT}}/node_modules/sw-toolbox/sw-toolbox.js'],\n      dest: '{{BUILD}}'\n    },\n    copyVirtualScrollCore: {\n      src: ['{{ROOT}}/node_modules/stenciljs-virtual-scroll/dist/virtualscroll/**/*'],\n      dest: '{{BUILD}}/virtualscroll'\n    },\n    copyVirtualScroll: {\n      src: ['{{ROOT}}/node_modules/stenciljs-virtual-scroll/dist/virtualscroll.js'],\n      dest: '{{BUILD}}'\n    }\n  }\n```\n\nbefore copyVirtualScrollCore property set standart app-script copy.config properties (if you are modify self config or my version is outdated, get only last 2 properties and put in your)\n\n3.  And register component in app module\n\n```ts\n....\nimport 'stenciljs-virtual-scroll/dist/virtualscroll';\n....\n\n``` \n\n4. rebuild\n\n# Usage\n\n\n```html\n....\n  \u003cdiv class=\"virtual-container\"\u003e\n    \u003cvirtual-scroll #scroll bottom-offset=\"5\" selector=\"page-example .scroll-content\"\u003e\n\n      \u003cdiv slot=\"virtual\" class=\"virtual-slot\"\u003e\n        \u003cdiv class=\"offer virtual-item\" [attr.id]=\"item.index\" *ngFor=\"let item of virtual\"\u003e\n          \u003cdiv [style.backgroundImage]=\"'url(' + item.thumbnailUrl + ')'\" class=\"cover\"\u003e\n          \u003c/div\u003e\n          \u003cdiv class=\"title\"\u003e{{item.index}}\u003c/div\u003e\n          \u003cdiv class=\"title\"\u003e{{item.title}}\u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n      \u003cdiv slot=\"loader\"\u003eloading...\u003c/div\u003e\n    \u003c/virtual-scroll\u003e\n  \u003c/div\u003e\n....\n```\n\nOR without selector\n\n```html\n....\n  \u003cdiv class=\"virtual-container\"\u003e\n    \u003cvirtual-scroll #scroll bottom-offset=\"5\" selector=\"\"\u003e\n\n      \u003cdiv slot=\"virtual\" class=\"virtual-slot\"\u003e\n        \u003cdiv class=\"offer virtual-item\" [attr.id]=\"item.index\" *ngFor=\"let item of virtual\"\u003e\n          {{item.index}}\n      \u003c/div\u003e\n      \u003cdiv slot=\"loader\"\u003eloading...\u003c/div\u003e\n    \u003c/virtual-scroll\u003e\n  \u003c/div\u003e\n....\n```\n\n\n```ts\n....\nexport class ExamplePage {\n\n  @ViewChild('scroll') vscroll: ElementRef;\n  private virtual: Array\u003cany\u003e = [];\n  ....\n\n  initVScroll() {\n\n    this.vscroll.nativeElement.addEventListener('update', (event) =\u003e {\n      this.virtual = event.detail;\n      //this.changeDetector.detectChanges(); if need\n    });\n\n    this.vscroll.nativeElement.addEventListener('toBottom', (event) =\u003e {\n      this.http.get('https://jsonplaceholder.typicode.com/photos', {}).map(res =\u003e res.json()).subscribe(data =\u003e {\n        this.vscroll.nativeElement.list = this.vscroll.nativeElement.list.concat(data.splice(0, 50))\n\n        if (this.vscroll.nativeElement.list.length \u003e 200) {\n          this.vscroll.nativeElement.setInfinateFinally();\n        }\n        else {\n          this.vscroll.nativeElement.setInfinateOn();\n        }\n        //this.changeDetector.detectChanges(); if need\n      });\n    });\n\n    this.http.get('https://jsonplaceholder.typicode.com/photos', {}).map(res =\u003e res.json()).subscribe(data =\u003e {\n      this.vscroll.nativeElement.list = data.splice(0, 50);\n        //this.changeDetector.detectChanges(); if need\n    });\n\n\n  }\n}\n\n....\n```\n\n```css\nvirtual-scroll {\n    display: block;\n}\n```\n\nIf you need to use it without framework, watch fetch-helper component.\n\n\n# Ionic 3 example\n\n[stenciljs ionic-virtual-scroll-example](https://github.com/mgnstudio7/ionic-virtual-scroll-example)\n\n# API\n\n**Selector** \n\nIn this attribute you must set selector of scrollable container (ionic application example).\nIf attribute is empty, component use inner scroll container.\n\n**bottom-offset** \n\noffset of elements to fired toBottom() event\n\n**toBottom()** \n\nthis event is fired if scroll came to the end\n\n**update()** \n\nthis event is fired every time when virtual scroll data is changed\n\n**setInfinateOn()** \n\nthis method must call every time when lazy load data is finish.\nIf this method do not call. toBottom event never fired again\n\n**setInfinateFinally()** \n\nthis method must call if lazy load finally and never fired toBottom() evend, and hide loader element\n\n**clear()** \n\nthis method clear all need params of component, but not list\n\n```ts\n....\n    this.vscroll.nativeElement.list = [];\n    this.vscroll.nativeElement.clear(); \n    //this.changeDetector.detectChanges(); if need     \n....\n```\n\n**scrollToNode()** \n\nset list item index, duration, offset\n\n```ts\n....\n    this.vscroll.nativeElement.scrollToNode(25, 1000, -50);\n....\n```\n\n**forceUpdateComponent()** \n\nthis method re-checks all dimensions, add the missing ones and force update component\n\n```ts\n....\n    this.vscroll.nativeElement.forceUpdateComponent();\n....\n```\n\n**virtual-ratio** \n\nadd nodes after last and before first viewed nodes in viewport.\n\n# WARN\n\nnodes(list items) index must be different. Component set different index but if you change it, or if your list contain dublicates there may be problems.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgnstudio7%2Fstenciljs-virtual-scroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmgnstudio7%2Fstenciljs-virtual-scroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgnstudio7%2Fstenciljs-virtual-scroll/lists"}