ublaboo/datagrid: mocný, rychlý, rozšiřitelný, hezký, anglicky dokumentovaný datagrid
- David Grudl
- Nette Core | 8218
Pavel Janda napsal(a):
Píšu si issue – nastavení defaultních hodnot filtru.
Aha, myslel jsem, že k tomu slouží
$grid->setFilter(['filterName' => 'value'])
, což mi funguje,
ale pravda, slovo default
by v názvu bylo popisnější.
Nějaké nápady na ověřenou JS knihovnu, která zpříjemní práci s multiselectem?
Používám Select2. Jeho chování je pro multiselect s tolika položkami, že při rozkliknutí nejsou vidět všechny najednou, ideální.
- TomasG
- Člen | 23
Ahoj,
prvně bych chtěl říct, že tento grid je přímo excelentní :o)
a dále mám menší dotaz:
Mám problém s překladem confirmů u akcí (používám
Kdyby\Translation).
ve slovníku mám
...
confirm:
delete: 'Opravdu chcete odstranit roli %name%?'
Ale nevím jak tam poslat ten parametr %name%.
Klasicky přes ->setConfirm('confirm.delete', 'name');
se tam
parametr nedostane. V případě callbacku si můžu zprávu přeložit sám ve
funkci, ale jelikož má grid nastavený translator, tak se pořád snaží
i ten výsledný confirm přeložit sám.
- Pavel Janda
- Člen | 977
@DavidGrudl DataGrid::setFilter()
je násilné nastavení
filtru. Tedy i pokud uživatel změní hodnoty filtru a později přijde na
stejný grid, bude ten filtr nastavený tak, jak chce metoda
setFiter()
přesto, že je třeba uloženo něco jiného
v session.
Něco jako DataGrid::setDefaultFilter()
by pak nemělo
přepisovat případná data v session. Rozepíšu to potom v dokumentaci, ať
je to jasné.
@TomasG To je bug. Do překladače by se samozřejmě měl hnát jen ten string s dynamickým placeholderem. Je to fixnuté, zatím v masteru. Pokud je v confirmation dialogu nastaven callback, měl by vracet již přeložený string.
Editoval Pavel Janda (19. 4. 2016 12:06)
- David Grudl
- Nette Core | 8218
Ještě pár věcí:
- když vypnu stránkování
$grid->setPagination(FALSE)
, asi by se nemusel zobrazovat spodní panelrow-grid-bottom
, kde vlastně nic není (a možná by mohl být renderován jako řádek tabulky, aby byl stejně široký, když tabulka nemá width: 100%) - u aktivování
$('.datagrid [data-sortable]')
by bylo fajn přidat optionaxis: 'y'
a taktéž ikonu změnit zfa-arrows
nafa-arrows-v
if (typeof $('.datagrid [data-sortable]').sortable === 'undefined') {
dělá zbytečný dotaz nad DOM, stačíif (typeof $.fn.sortable === 'undefined') {
- ačkoliv dokumentace trošku (a asi nechtě) naznačuje opak, tak
datagrid.js
musí být natažen až na konci stránky. Nestálo by za to ty inicializace nad DOM přesunout do$(function() { … })
?
- David Grudl
- Nette Core | 8218
Trik, jak zamezit, aby se přesouvanému řádku nezměnily šířky sloupců:
return $('.datagrid [data-sortable]').sortable({
helper: function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
},
…
- Pavel Janda
- Člen | 977
@DavidGrudl Stránkování: Je tam ještě třeba někde zobrazit button, který umožní resetování filtru. Přidám do šablony podmínku (nepoužívám filtry && nepoužívám stránkování ⇒ skryj patičku).
Zapřemýšlím nad tím řádkem tabulky. Dřív tam byl nějaký problém ohledně snippetů, ale už to myslím není aktuální.
Díky za poznámky. Do masteru jsem dal pozměněné assety.
- sepo
- Člen | 69
Pavel Janda napsal(a):
Nová verze – v3.3.0
- Inline přidávání záznamů, http://ublaboo.paveljanda.com/datagrid/add
Ahoj
„plus“ button je v hlavičke a riadok pridáva na koniec
je možné ho renderovať ako prvý riadok/resp. do hlavičky ?
- Pavel Janda
- Člen | 977
@sepo Dobrý nápad. Zatím v masteru, bude v příští verzi. Api:
$grid->addInlineAdd()->setPositionTop();
, opětovaného
nastavení renderování dole je docíleno toutéž metodou, akorát
s argumentem FALSE.
- darkweaver
- Člen | 18
Ahoj, prvně bych chtěl poděkovat za parádní DataGrid, je opravdu super. Chtěl bych se ale zeptat, jakým způsobem zpracováváte chyby vzniklé při inline editaci/přidávání nové položky přes DataGrid?
Když datagrid umožňuje přidávání/editaci přímo v tabulce, a vypisovaných dat je málo(cca 3 sloupečky), tak mi přišlo zbytečné přidávat další stránku jen pro přidávání/editaci záznamů dané entity.
Jak ale řešíte situaci, kdy na jednom sloupci je nastaven například unique key, nebo hodnota v jednom sloupci nesmí být větší než hodnota v druhém sloupci apod.?
Normálně mi z aplikace přijde například vyjímka, kterou bych zpracoval a vyhodil flash message. Jak ale takovou chybu zobrazit? Zobrazit flash message nad datagridem? Když bude počet položek na jedné stránce větší, tak flash message nad datagridem a položka někde dole nebude moc user friendly.
Zkoušel jsem i hodit formulář do detailu položky, což se mi povedlo, ale nepřišel jsem už na to, jak tam dostat defaultní hodnoty zobrazované entity, pokud by to ale šlo, jak bych tam mohl zobrazit tu chybovou zprávu?
Nebo se na to dívám úplně špatně a měl bych v inline editaci povolit pouze změnu hodnot, u kterých k takové chybě nedojde?
Díky moc za odpovědi.
- Pavel Janda
- Člen | 977
@darkweaver Nad složitějšími chybovými hláškami jsem zatím
nepřemýšlel. Používají se ale nette forms, takže validační pravidla by
se měla aplikovat již v JS. Ale za jakýkoliv další nápad budu rád.
Na druhou stranu, vyrábění nějaké větší entity přes inline
přidávání záznamů v datagridu mi přijde trochu hardcore.. Ale jak
říkám, nebráním se dalším nápadům, jak takové počiny
zpříjemnit.
Inline přidávání záznamů je momentálně jediná věc, která se netahá pomocí snippetu. Kdyby se tahala, tak by tam asi šly dostat normální formulářové ajaxové validace. Zatím jsem nepřišel na způsob, jak toho docílit v té tabulce. Možná na to ještě přijdu.
Defaultní hodnoty ve velké inline editaci nastavíš pomocí eventu
InlineEdit::onSetDefaults
, http://ublaboo.paveljanda.com/datagrid/edit#…
Defaultní hodnoty ve formuláři detailu položky můžeš nastavit v šabloně, http://ublaboo.paveljanda.com/datagrid/action#…
- David Grudl
- Nette Core | 8218
Ještě k těm přesouvacím ikonkám – viděl jsem, že teď se ikonka při přesouvání změní z 🕂 na ↕ což mi ale úplně nedává smysl, respektive nerozumím, proč mít vůbec pro přesun nahoru/dolů ikonku 🕂 znamenající přesun ve všech směrech?
Určitý problém z hlediska UI je také zobrazení této ikonky v podobě
buttonu, protože to tlačítko není, je to prostě táhlo, viz třeba
použití na https://jqueryui.com/sortable/. Chápu, že důvodem asi je
snaha o jednotný vzhled ikon v sloupci Action, ale toho bych se vůbec
nebál, odstranění tlačítka (obrázek vlevo) na vzhledu neubírá a na
srozumitelnosti určitě přidá (fa fa-arrows-v fa-lg
):
- Pavel Janda
- Člen | 977
@DavidGrudl 2, Souhlasím, že se to nechová jako klasické tlačítko. Na druhou stranu, značí to nějakou akci – když kliknu (podržím), něco se stane. Pouze ikonka tak, jak je na screenshotu nalevo, se mi nezdá tak proaktivní jako napravo.
1, Taky bych s tím souhlasil. Ale obyčejní lidé jsou spíš zvyklí na symbol té čtyřšipičky, alespoň na mě působí spíš jednoduchým dojmem „přesunou“, než „Vzít, táhnout – proč to nejde od všech stran??“..
Udělám s pár lidmi nějaký jednoduchý testing, abych získal náhled ze strany bfu.
Dík za postřehy
Editoval Pavel Janda (20. 4. 2016 14:14)
- Jakub Kontra
- Člen | 30
David Grudl napsal(a):
Ještě k těm přesouvacím ikonkám – viděl jsem, že teď se ikonka při přesouvání změní z 🕂 na ↕ což mi ale úplně nedává smysl, respektive nerozumím, proč mít vůbec pro přesun nahoru/dolů ikonku 🕂 znamenající přesun ve všech směrech?
Určitý problém z hlediska UI je také zobrazení této ikonky v podobě buttonu, protože to tlačítko není, je to prostě táhlo, viz třeba použití na https://jqueryui.com/sortable/. Chápu, že důvodem asi je snaha o jednotný vzhled ikon v sloupci Action, ale toho bych se vůbec nebál, odstranění tlačítka (obrázek vlevo) na vzhledu neubírá a na srozumitelnosti určitě přidá (
fa fa-arrows-v fa-lg
):
Pavel Janda napsal(a):
@DavidGrudl 2, Souhlasím, že se to nechová jako klasické tlačítko. Na druhou stranu, značí to nějakou akci – když kliknu (podržím), něco se stane. Pouze ikonka tak, jak je na screenshotu nalevo, se mi nezdá tak proaktivní jako napravo.
1, Taky bych s tím souhlasil. Ale obyčejní lidé jsou spíš zvyklí na symbol té čtyřšipičky, alespoň na mě působí spíš jednoduchým dojmem „přesunou“, než „Vzít, táhnout – proč to nejde od všech stran??“..
Udělám s pár lidmi nějaký jednoduchý testing, abych získal náhled ze strany bfu.
Dík za postřehy
Souhlasím s @DavidGrudl. Varianta v levo (táhlo) je více uživatelsky přívětivá a určitě bych to tak rád viděl. Není tlačítko jako tlačítko
- David Grudl
- Nette Core | 8218
Pavel Janda napsal(a):
Udělám s pár lidmi nějaký jednoduchý testing, abych získal náhled ze strany bfu.
To je nejlepší cesta, paráda.
- Pavel Janda
- Člen | 977
@tatyalien K tomu bitbucketu: Úplně nevím, co všechno máš
v plánu s tou třídou ExampleFilter
, ale v podstatě může
tvoje Repository rovnou implementovat
Ublaboo\DataGrid\DataSource\IDataSource
: http://pastebin.com/LLcZ8uDe
Editoval Pavel Janda (27. 4. 2016 12:10)
- daliborK
- Člen | 3
Zdravím děkuji za skvělý Datagrid, opravdu vymakaný :-).
Potřeboval jsem do horní části grida vedle ikonek „Nový záznam“ a
„Skrýt sloupce“ přidat ještě jednu mnou definovanou (nějaký odkaz).
Rozšířil jsme si třídu \Ublaboo\DataGrid\DataGrid a přidal metodu
<?php
class Grid extends \Ublaboo\DataGrid\DataGrid {
protected $settingButtons;
public function __construct($parent, $name) {
parent::__construct($parent, $name);
}
/**
* muzes pridat element a zobrazi se v horni casti grida
* @param \Nette\Utils\Html $el
*/
public function addSettingButtons(\Nette\Utils\Html $el=null){
if($el){
$this->settingButtons[] = $el;
}
return $this;
}
public function render() {
$this->template->settingButtons = $this->settingButtons;
parent::render();
}
}
?>
a v šabloně upravit podmínky nad vykreslením $inlineAdd
přidal toto:
<?php
{if $settingButtons}
{foreach $settingButtons as $button}
{$button}
{/foreach}
{/if}
?>
Poté se dá použít takto:
<?php
...
$grid->addSettingButtons(\Nette\Utils\Html::el('a')
->href('print:pdf')
->setText('Tisk pdf')
);
?>
Co něco podobného přidat přímo do \Ublaboo\DataGrid\DataGrid?
- tatyalien
- Člen | 239
@PavelJanda
Ahoj, díky za nástřel, koukal jsem na to a zkusil to implementovat, ale
dostávám Fatal error: datagrid/src/DataSource/ArrayDataSource.php:221 přitom
ale mám nastavený dataSource na tu repository. Akutalizoval jsem bitbucket, konkrétně:
- presenter: createComponentExamplesGrid($name)
- repository: udělaný jen nástřel dle tebe
- Pavel Janda
- Člen | 977
@tatyalien Co se ti hází za chybu? Kdyžtak mi všechno piš prosím
na gitter. Btw, pokud chceš používat jako datasource tu repositoru, tak
nepiš
$grid->setDataSource($this->exampleRepository->getData());
,
ale $grid->setDataSource($this->exampleRepository);
.
- tatyalien
- Člen | 239
Pavel Janda napsal(a):
@tatyalien Co se ti hází za chybu? Kdyžtak mi všechno piš prosím na gitter. Btw, pokud chceš používat jako datasource tu repositoru, tak nepiš
$grid->setDataSource($this->exampleRepository->getData());
, ale$grid->setDataSource($this->exampleRepository);
.
Ahoj,
napsal jsem ti email, gitter neznám :) tak ať to tu nespamuji.
- romiix.org
- Člen | 343
@PavelJanda Vybral si nejaký multiselect? Kedy ho máš cca na pláne
implementovať? Potrebujem ho a ak by som sa k nemu dostal skôr ako ty, tak
nech pošlem rovno PR s doplnkom ktorý chceš aj ty.
Vďaka!
- Pavel Janda
- Člen | 977
@romiix.org Už je to pár dní v masteru. Otaguji to ve verzi 4.0.0 během dneška/zítřka.
- romiix.org
- Člen | 343
Pavel Janda napsal(a):
@romiix.org Už je to pár dní v masteru. Otaguji to ve verzi 4.0.0 během dneška/zítřka.
Vidím správne, že nie je použitý žiadny JS doplnok?
Tzn. filtrovací riadok sa proste natiahne a zobrazí sa štandardný HTML
multiselect.
Edit: Používa sa bootstrap-select.
Editoval romiix.org (2. 5. 2016 11:15)
- Pavel Janda
- Člen | 977
@romiix.org Ano, používá se bootstrap-select. Vše bude popsáno v docu v moment, co vydám v4. :)
- romiix.org
- Člen | 343
Je možné použiť vlastné zoradenie riadkov, ktoré neexistujú v DB?
Konkrétne: Ceny produktov sú dynamické a počítajú sa na základe
mnohých parametrov. Nie je problém ich vypísať cez
setRenderer()
, ale neviem ich zoradiť podla dodatočne
vypočítanej hodnoty.
->setSortableCallback()
mi nefunguje, resp. neviem ako metódu
použiť.
Skúšal som to nasledovne:
$grid->addColumnText('price', 'itemsGrid.price')
->setSortable()
->setSortableCallback(function($datasource, $sort) {
$datasource->order('FIELD(id, ?)', $this->itemModel->sortByPrice($datasource, $sort['price']));
});
Je to aktuálne riešiteľné?
Vďaka!
@PavelJanda Vlastne to funguje :) Vyriešené.
Editoval romiix.org (2. 5. 2016 17:56)
- Pavel Janda
- Člen | 977
@romiix.org http://ublaboo.paveljanda.com/datagrid/column#…
Tedy například:
$grid->addColumnNumber('id', 'Id')
->setSortable()
->setSortableCallback(function($fluent, $sort) {
$fluent->orderBy('name DESC');
})
Editoval Pavel Janda (2. 5. 2016 15:20)
- romiix.org
- Člen | 343
Pavel Janda napsal(a):
@romiix.org http://ublaboo.paveljanda.com/datagrid/column#…
Tedy například:
$grid->addColumnNumber('id', 'Id') ->setSortable() ->setSortableCallback(function($fluent, $sort) { $fluent->orderBy('name DESC'); })
Toto funguje, ak sa sort vykonáva ajaxovo prostredníctvom
handleSort()
. V tento metóde sa zavolá
$this->sort_callback = $column->getSortableCallback();
a nad tým istým objektom sa zavolá render()
.
Dostal som sa k tomu, že ak je v session nastavené zoradenie, tak sa
sortable callback nezavolá, pretože sa nenastaví do
$this->sort_callback
.
Editoval romiix.org (2. 5. 2016 19:48)
- Pavel Janda
- Člen | 977
Nová verze – v4.0.0
Vydal jsem novou verzi, kvůli změně latte šablony považuji novou verzi za možný bc break, více v posledním bodu seznamu níže.
- Šablony filtrů lze kromě bloků pojmenovaných podle jména filtru
definovat též typem filtrů, tím se aplikuje na všechny filtry stejného
typu (
{block filtertype-select}{/block}
), docu zde: http://ublaboo.paveljanda.com/datagrid/filter#… - Přibyl nový filter –
FilterMultiSelect
(používá frontendovou knihovnu bootstrap-select, jak nainstalovat se dozvíte na homepage docu), více zde: http://ublaboo.paveljanda.com/datagrid/filter#… - Iniline přidávání záznamů je možné nyní renderovat jak pod načtenými položkami, tak nahoře, více zde: http://ublaboo.paveljanda.com/datagrid/add#…
- Přibyla možnost definovat parametry latte bloku/šabloně pro item detail, více zde: http://ublaboo.paveljanda.com/datagrid/action#…
- K možnosti nastavit defaultní schování sloupců, přibyla další – zobrazit defaultní sloupce, více zde: http://ublaboo.paveljanda.com/datagrid/column#…
- Přibyla možnost změny chování překládání selectů u filtrů, více zde: http://ublaboo.paveljanda.com/…localization#…
- Přibyla možnost nastavit defaultní filtry datagridu, více zde: http://ublaboo.paveljanda.com/datagrid/filter#…
- Patička se přesunula z divů do
<tfoot>
, což znamená možný BC break pro ty, který si definují svou vlastní šablonu datagridu.
Díky všem za nápady a spolupráci!
Editoval Pavel Janda (4. 5. 2016 9:43)
- Pavel Janda
- Člen | 977
A ještě jedna věc: přibyl nový datasource: ApiDataSource
.
Je experimentální a netestoval jsem ho. Pokud ho někdo využije, piště, co
přidat/zlepšit. Moc tam toho asi nebude. ApiDataSource prostě forwarduje
filtrování, sortění a pod na remote api.
- daliborK
- Člen | 3
Zdravím trochu zápasím s inline editací:
- je možné po kliku na tlačítko „save“ překreslit celý dataGrid a né jenom konkrétní řádek? Zkoušel jsem obalit dataGrid do snippetu a zavolat $this->redrawControl(), ale poté se zobrazí pouze editovaný záznam.
- do formuláře inline editace bych potřeboval dostat něco jako $form->addError(‚xx‘). V podstatě zabránit uložení a zobrazit chybovou hlášku. Je to možné?
Děkuji za jakýkoli nápad.
- Pavel Janda
- Člen | 977
@daliborK
- Momentálně ne, onSubmit event se triggeruje před překreslením řádku, takže moc do datagridu v tu chvíli šáhnout nelze. Můžeš založit issue.
- Už je založena issue s validací inline formuláře.
- Ripper
- Člen | 56
Zdravím všechny,
rád bych se zeptal zda někdo nemáte slušně udělaný handle na sort (ukládání seřazených prvků). Trochu s tím zápasim, jakš takš mi to funguje, ale má to asi 45 řádků a vůbec se mi to nelíbí. Proto se obracím na ty zkušenější, zda by někdo nenabídl svůj snippet.
Díky za odpovědi, rady. Ripper.
- fizzy
- Backer | 49
@Ripper akurat sme to tiez riesili, najednoduchsie co ma napadlo:
public function handleSort($item_id, $prev_id, $next_id){
$prevRow = $this->database->table("tabulka")->where("id", $prev_id)->fetch();
$newOrderId = $prevRow ? $prevRow->position + 1 : 1;
$this->database->query("UPDATE tabulka SET position = position + 1 WHERE position >= ?", $newOrderId);
$this->database->query("UPDATE tabulka SET position = ? WHERE id = ?", $newOrderId, $item_id);
}
- pitr82
- Člen | 121
Mám dotaz,
pokud používam změnu stavu pro řádek (status), již se mi nezmění css
třída, která v mém případě obarvuje řádek.
Zavolá se onChange[], kde se provede redraw řádku provede se změna stavu, a
pak se vola setRowCallback() kde se změní class prvku na základě stavu, ale
už se neaplikuje redraw řádku.
Jak docílit, aby se změnila i class prvku ?
$grid->setRowCallback(function($item, $tr) {
$tr->addClass('super-' . $item->id);
$this['columnsGrid']->redrawItem($id);
});
- Pavel Janda
- Člen | 977
@pitr82 Hmm, to je trošku trouble. Bohužel, momentálně je v kódu
<tr n:snippet="item-...">
, takže se překresluje pouze obsah
elementu <tr>
. A obalit <tr>
snippetem
nelze, protože samotný snippet vytvoří div a <tbody>
nesmí obsahovat přímo div. :P
Dáš to pls na github do issues? Nějak to vymyslíme.
- sibka
- Člen | 24
@PavelJanda Opět musím pochválit vývoj gridu.
Ale bohužel mi po upgradu nefunguje nastavení výchozího filtru. Mám:
$grid->setDefaultFilter(array(‚datum‘ => –2),true);
$grid->addColumnDateTime(‚datum‘, ‚Datum‘)
->setFilterSelect(…
A píše mi to „Filter [datum] is not defined“.
Omlouvám se za kód, nějak mi to nejde pěkně vložit.
Editoval sibka (12. 5. 2016 7:44)
- Pavel Janda
- Člen | 977
@sibka dej definici sloupce/filtru pred ty defaultni hodnoty. Je tam check, aby to spis vyvojare nutilo napsat spravne klice defaultnich hodnot, nez aby to v tichosti proslo a nic se pak nezobrazilo.
- romiix.org
- Člen | 343
Je aktuálne nejak možné zakomponovať závislé filtre?
Konkrétne by som potreboval, aby sa dalo pri plnení filtrov dalo pristúpiť
k odfiltrovanému datasourcu na základe predošlého vyplnenia. Tzn.
zaškrtnem výrobcu Toyota a ponúkne mi iba autá zodpovedajúce
danému výrobcovi, atď.
Pre nastavenie korektných hodnôt je potrebné mať k dispozícií aktuálny
zoznam odfiltrovaných áut. To by bolo riešiteľné vyňatím zodpovednej
sekvencie z render metódy do novej metódy getRows.
Metóda je dostupné v továrničke a vieme zobrazovať položky na základe
zostávajúcich možností.
Zložitejší problém je, ako aktualizáciu filtra zobraziť. Dalo by sa
pridať snippet pre riadok s filtrami, ale to by spôsobilo nepríjemný
problém pri multiselecte – po označení niektorej položky by sa výber
skryl. To by sa asi dalo riešiť snippetmi na úrovni <ul>
elementov. Je tento prístup správny? Nejaký iný nápad..?
- Pavel Janda
- Člen | 977
@romiix.org Není. Ale není problém si ho přidat. Prostě přidej inputu filtru třídu, nebo data atribut a vyrob si nějaké api, kde budeš předávat data z (pravděpodobně) databáze.
Nic takového ale implementovat neplánuti. Proč:
- Je to megajenoduché implementovat s vlastní oblíbenou suggest knihovnou
- Jelikož se všechna data filtrují ajaxově a v reálném čase, přijde mi suggest zbytečný.
K těm závislým filtrů: Já osobně bych to tady asi řešil spíš pomocí dalšího formuláře, který by byl nad datagridem a sám bych mu předával filtrovaný datasource. Ale jak jsi psal, není to problém nějak ohnout, problém je to ohnout tak, aby ti nezmizel focus z toho pole.
Editoval Pavel Janda (15. 5. 2016 14:44)
- Pavel Janda
- Člen | 977
Nová verze – v4.1.0
- Bug fixes (@FJP)
- Přidána možnost zobrazit SUM vybraných sloupců pod tabulkou (příklad: http://ublaboo.paveljanda.com/datagrid/, doc: http://ublaboo.paveljanda.com/datagrid/column#…)
Editoval Pavel Janda (18. 5. 2016 18:57)
- FJP
- Člen | 124
- Bug fixes (@FJP)
- Přidána možnost zobrazit SUM vybraných sloupců pod tabulkou (příklad: http://ublaboo.paveljanda.com/datagrid/, doc: http://ublaboo.paveljanda.com/datagrid/column#…)
Stáhnul jsem novou verzi a chová se mi to trošku podivně:
Pozn: chová se to stejně i když jsou v gridu nějaké řádky
Editoval FJP (19. 5. 2016 9:51)