composer require contributte/uiservices:
latte.latteFactory:
setup:
- addExtension(App\Model\ViteExtension(%wwwDir%/dist/manifest.json, /dist))The Vite extension automatically supports Content Security Policy nonces via the uiNonce variable provided by nette/application.
{vitejs 'assets/js/app.js'}
{vitecss 'assets/js/app.js'}When nonce is available, it's automatically injected:
<script type="module" src="/dist/app.js" nonce="..."></script>
<link rel="stylesheet" href="/dist/app.css" nonce="...">To use nonce support, ensure your Nette application sets the nonce value in presenter or middleware:
$nonce = base64_encode(random_bytes(16));
$this->template->uiNonce = $nonce;
header("Content-Security-Policy: script-src 'nonce-{$nonce}'; style-src 'nonce-{$nonce}'");Register the factory:
services:
- Contributte\UI\Paginator\PaginatorControlFactoryCreate a data provider:
use Contributte\UI\Paginator\ArrayDataProvider;
use Contributte\UI\Paginator\PaginatorDataProvider;
use Nette\Utils\Paginator;
// Using built-in ArrayDataProvider
$provider = new ArrayDataProvider($data);
// Or implement your own
class MyDataProvider implements PaginatorDataProvider
{
public function page(Paginator $paginator): array
{
$paginator->setItemCount($this->getTotalCount());
return $this->fetchItems($paginator->getOffset(), $paginator->getLength());
}
}Use in presenter:
use Contributte\UI\Paginator\PaginatorControlFactory;
class ArticlePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private PaginatorControlFactory $paginatorFactory,
) {}
protected function createComponentPaginator(): PaginatorControl
{
$provider = new ArrayDataProvider($this->articles);
$control = $this->paginatorFactory->create($provider, itemsPerPage: 10);
$control->onPagination[] = fn() => $this->redrawControl('articles');
return $control;
}
public function renderDefault(): void
{
$this->template->articles = $this['paginator']->getPage();
}
}Render in template:
<div n:snippet="articles">
<div n:foreach="$articles as $article">...</div>
{control paginator}
</div>Custom template:
$control->setTemplateFile(__DIR__ . '/templates/myPaginator.latte');Built-in templates: bootstrap4.latte, bootstrap5.latte (default).
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig(({ mode }) => {
const DEV = mode === 'development';
return {
resolve: {
alias: {
'@': resolve(__dirname, 'assets/js'),
'~': resolve(__dirname, 'node_modules'),
},
},
server: {
open: false,
hmr: false,
},
build: {
manifest: true,
assetsDir: '',
outDir: './www/dist/',
emptyOutDir: false,
minify: DEV ? false : 'esbuild',
rollupOptions: {
output: {
manualChunks: undefined,
chunkFileNames: DEV ? '[name].js' : '[name]-[hash].js',
entryFileNames: DEV ? '[name].js' : '[name].[hash].js',
assetFileNames: DEV ? '[name].[ext]' : '[name].[hash].[ext]',
},
input: {
app: './assets/js/app.js'
}
}
},
}
});Thanks for testing, reporting and contributing.