Částečná aktualizace stránky - partial update
Částečná aktualizace stránky - partial update
Edee.one rozhraní pracuje v ui s konceptem tzv. panelů, které se v jedná stránce postupně otevírají a modifikují její obsah. Nedochází tedy k přenačítání celé stránky, ale k úpravám domu jednou načtené stránky pomocí javascriptu.
Tento přístup je úzce spjatý s technikou partial update (také jako částečná výměna obsahu) - která umožnuje vracet ze serveru pouze fragmenty stránek a ty potom v prohlížeči vkládat na správné místo.
Stejného mechanizmu se použivá i při synchronizaci ui se stavem na serveru pomocí tzv. refresh event.
Technicky je použitý partial update RamJet frameworku, ze kterého Edee UI vychází. Obecně se využívá:
- page manager - script běžící ve stránce starající se o správu panelů - rychlých oken, které se skládají v ui nad sebe
- layout context - mechanizmus RamJetu, který zajisťuje prefixování DOM identifikátorů ve spojení s page managerem
- partial update - script běžící ve stránce který provádí volání fragmentů stránek na základě nastavení v data atributech (v datasetu)
- jsPartialUpdate - RamJet komponenta pro vymezení chování partial update mechanismu
Zkopírovat odkaz na sekciNastavení partial update na úrovni komponent
Primárně se váže na javascript událost spojenou s komponentou, např. při změně hodnoty. Definuje se v metadatech komponenty (odtud se nastavení kopírují do datasetu).
- partialUpdate specifikace javascript události po které je partial update zahájen
- partialUpdateTarget, partialUpdateWidget identifikátor widgetu, který chceme načíst ze serveru (při použití transparentControl je výsledkem pouze base komponenta, nikoliv obsah včetně kontejneru)
- partialUpdateEventName, partialUpdateCommand umožňuje specifikovat název ramjet události, která bude vyvolána na straně serveru
- partialUpdateSettings dodatečné vlastnosti po parametrizaci partial update požadavku
Pozor: Při kopírování hodnot partialUpdateTarget a partialUpdateWidget dochází k automatickému prefixování layoutContext, pokud je takový kontext pro vykreslení stránky použit. V rámci těchto metadat je také možné použít konstantu thisWidget, která použije id komponenty, ve které jsou metadata definována. Z tohoto důvodu není vhodné zapisovat metadata vztahující se k partialUpdate přímo do cílového dataset kontejneru.
Dotaz na widget, který je součástí transparentControl se bere v potaz pouze vnitřní komponenta, pokud je navíc tato komponenta obohacena podmínkou s renderOn pak je tato podmínka ignorována!
Zkopírovat odkaz na sekcipartialUpdateSettings vlastnosti
| Název dataset vlastnosti | Možné hodnoty | Default | Popis |
|---|---|---|---|
| target | string, Array | false | id widget na serveru, nebo seznam id |
| url | string | null | nastavení url cílové stránky, pokud není nastavena je vypočítáno automaticky |
| requestTarget | string | null | volitelně přetížení id widgetu na serveru, který se použije místo target hodnoty |
| eventName, command | string | null | umožňuje specifikovat název ramjet události, která bude vyvolána na straně serveru (může přetížit hodnotu z partialUpdateEventName) |
| data | Object | null | dodatečné parametry (název, hodnota), které budou součástí partial update požadavku na server |
| dataMerge | Object | null | dodatečné parametry s možností přetížení. Data se budou mergovat s odesílanými, tj. pokud v mergeDatech bude parametr, který je ve formuláři nebo url, tak bude přepsán |
| exceptParams | Array | null | seznam parametrů, které se nemají na server odesílat - hodnoty oddělené čárkou |
| historyScope | none,parameters,allData | allData | Vkládá do historie prohlížeče v rámci záměny obsahu i původní url s vybranými vstupními parametry, které umožní stránku správně obnovit. Je možné vybrat pouze nic, pouze parametry nebo parametry a všechna data komponent. Při poslední volbě je nutné zvážit omezení na délku URL. |
| removeContainerWidgetData | Array | null | TODO neodešle na server widget data (frm.) uvnitř aktualizovaného targetu |
| timeout | number | 60000 | timeout v ms pro response ze serveru |
| layoutContext | string | null | pro propagaci layout context id prefixu |
| submitId | string | null | id formuláře nebo tlačítka uvnitř formuláře TODO k čemu? |
| scroll | boolean,top,bottom | false | příznak zascrolování po zpracování výsledku TODO funguje v edee? |
| scrollOffset | number | 25 | počet px zascrolování po zpracování výsledku |
| scrollDuration | number | 200 | délka animace scrolování |
| globalTarget | string | dynamicArea | využívá se při pohybu historie, mělo by to být id elementu, které se nachází na každé stránce webu |
| pick | Array | false | pole selectorů, které se mají nahradit |
| omit | Array | false | pole selectorů, které se nemají nahrazovat |
| headers | Object | null | doplňkové hlavičky požadavku na server |
| type | String | POST | http metoda požadavku TODO funguje? |
| ajax | Object | null | odstraněno (využívala původní jquery implementace) |
Zkopírovat odkaz na sekcipartialUpdateSettings příznaky
| Název dataset vlastnosti | Možné hodnoty | Default | Popis |
|---|---|---|---|
| alterHistory | boolean | false | nastavení, zda se má po dokončení PU zaktualizovat history state prohlížeče |
| removeFormId | boolean | false | příznak zda při požadavku odstranit identifikátor konverzace (pro formPage bude požadavek součástí nové konverzace) |
| removeFormWidgetData | Array, boolean | null | příznak (nebo seznam parametrů) pro vynechání widget dat parametrů (frm.) na server |
| suppressRedirect | boolean | false | pokud je odpověd ze serveru 302 pak - false vynutí refresh stránky, jinak zpracuje výsledek přesměrování |
| cache | boolean | false | příznak XHR požadavku pro cachování TODO používá se? |
| rememberPagination | boolean | false | příznak zda využít hodnotu stránkování - hledá element s atributem data-fragment="pagination" a na něm aktuální stav stránkování |
| disposeAndDecorateLifecycle | boolean | true | příznak pro korektní destroy lifecycle všech vnořených web komponent |
| generateReplacementContainer | boolean | false | příznak jestli se má nahrazovaný obsah obalit do DIV elementu s css třídou "partialUpdateDynamicContainer" |
| formsChangesDetection | boolean | false | příznak kterým se aktivuje kontrola modifikovaného formuláře, která přeruší akci a zavolá onFormsChangesDetect |
| includeToProgress | boolean | true | příznak zda je žádoucí zobrazovat identifikace běžící akce (probress bar, spinner) |
| mergeWithTargetSettings | boolean | true | příznak, který který určuje, zda přebírat nastavení z dataset atributů z dom prvku dle hodnoty target nebo submitId |
| dataFromAllFormsInDocument | boolean | true | příznak určuje jestli se se mají na server odesílat data ze všech formulářu v documentu (true), které mají stejný atribut action. Pokud se v nejakých formulářích vyskytují stejná widget data, tak se na server odešlou jen z prvního formuláře |
| historyReplaceState | boolean | false | příznak zda po úspěšném vykonání PU je do historie prohlížeče proveden push nebo replace |
| persistFocus | boolean | true | příznak který zajišťuje zachování focusu ve formuláři, uvnitř input elementů zachovává i pozici kurzou |
| moveUrlQueryParamsToFormDataOnPost | boolean | false | při POST požadavku převede všechny query parametry jako form data. Eliminuje tak problém s dlouhou url, což bývá maximálně 2083 znaků. |
| clearCache | boolean | null | odstraněno (využívala původní jquery implementace) |
Zkopírovat odkaz na sekcipartialUpdateSettings funkce pro vlastní rozšíření
| Název dataset vlastnosti | Možné hodnoty | Default | Popis |
|---|---|---|---|
| onAlterHistory | function | null | callback funkce |
| onError | function | null | funkce která se zavolá v případě vyskytnutí se chyby během vykonání partial updatu. Jde např. využít pro zobrazení dialogu s chybou |
| onAfterContentsReplace | function | null | callback funkce |
| onComplete | function | null | callback funkce |
| replaceContents | function | null | custom replace funkce |
| replaceTargetContent | function | null | custom replace funkce |
| onBeforeContentsReplaced | function | null | callback funkce |
| onFormsChangesDetect | function | null | callback funkce |
| onBeforeExecute | function | null | callback funkce |
Zkopírovat odkaz na sekcihodnoty nastavitelné v datasetu mimo partialUpdateSettings
Tyto hodnoty lze doplnit přímo do datasetu komponenty, případné stejné hodnoty v partialUpdateSettings mají vyšší prioritu.
- partialUpdateUrl nastavení url cílové stránky, pokud není nastavena je vypočítáno automaticky
- partialUpdateRequestTarget, partialUpdateTargetHtmlContainer Id elementu, který pomocí PU chceme zaktualizovat (pokud je potřeba ze serveru načíst jiný container než je na clientu nahrazován)
- partialUpdateData Dodatečné parametry (název, hodnota), které budou součástí partial update požadavku na server.
- partialUpdateAlterHistory Příznak, zda se má po dokončení PU zaktualizovat history state prohlížeče
Je možné použít i variantu s náhradou partialUpdate za pu - např. puUpdateUrl - zkrácené varianty mají vyšší prioritu než plné, ale nižsí než hodnoty v partialUpdateSettings.
Zkopírovat odkaz na sekcipříklady
Přenačtení po akci komponenty
1 <!-- po výběru hodnoty dojde k přenačtení widgetu "objectPreview" -->2<tileButtonSelect id="pageTreePrototype">3 <dataSource type="selectablePrototypesProvider"/>4 <metadata>5 <icon>[#item[].properties[icon]#]</icon>6 <partialUpdate>change</partialUpdate>7 <partialUpdateWidget>objectPreview</partialUpdateWidget>8 </metadata>9</tileButtonSelect>
1 <!-- po uploadu dojde k aktualizaci "record" komponenty a vyvolání command eventy "updateWarning" -->2<uploadButton id="upload">3 <metadata>4 <partialUpdate>uploadcomplete</partialUpdate>5 <partialUpdateWidget>record</partialUpdateWidget>6 <partialUpdateCommand>updateWarning</partialUpdateCommand>7 </metadata>8</uploadButton>
1 <!-- alternativní definice settings přímo v datasetu -->2<baseReactSelect id="webId">3 <dataSource type="cpsWebSelectableItemsProvider"/>4 <metadata>5 <partialUpdate>change</partialUpdate>6 <partialUpdateTarget>layout</partialUpdateTarget>7 <dataset>8 <puSettings>9 <exceptParams>parentId</exceptParams>10 </puSettings>11 </dataset>12 </metadata>13</baseReactSelect>
Modifikace možností refreshEvent
1 <!-- refresh porvést bez odeslání widget dat (frm parametrů) -->2<nestedGrid id="grid">3 <metadata>4 <dataset mode="combine">5 <refreshEvent>6 <event>updateFile, moveFile</event>7 <puSettings>8 <removeFormId>false</removeFormId>9 <removeFormWidgetData>true</removeFormWidgetData>10 </puSettings>11 </refreshEvent>12 </dataset>13 </metadata>14 ..15</nestedGrid>
1 <!-- refresh provede jako GET -->2<relatedPagesSelect id="localizedPagesTreeSelect">3 <dataSource type="relatedPagesDataProvider" category="LOCALIZE" />4 <population type="alwaysClear"/>5 <metadata>6 <dataset>7 <refreshEvent>8 <event>createLocalization</event>9 <validAttributes>10 <sourceId>#widget[record].record.primaryKey!0#</sourceId>11 </validAttributes>12 <puSettings>13 <removeFormId>true</removeFormId>14 <removeFormWidgetData>true</removeFormWidgetData>15 <type>GET</type>16 </puSettings>17 </refreshEvent>18 </dataset>19 </metadata>20</relatedPagesSelect>
nastavení přímo v data atributech
Jsou podporovány následující hodnoty:
- data-partial-update
- data-partial-update-url, data-pu-url
- data-partial-update-request-target, data-pu-request-target
- data-partial-update-target-html-container, data-pu-target-html-container
- data-partial-update-target, data-pu-target, data-partial-update-widget, data-pu-widget
- data-partial-update-command, data-pu-command, data-partial-update-event-name, data-pu-event-name
- data-partial-update-data, data-pu-data
- data-partial-update-alter-history, data-pu-alter-history
- data-partial-update-settings, data-pu-settings
Ostatní lze vložit jako JSON přímo do data-pu-settings.
Příklad použití definice přímo ve FTL šabloně
1 <div data-pu-url="<@qf.pageUrl urlToIdentify="/edee/comment/addComment?ot=${comment.objectType}&oi=${comment.objectId}&rot=edeeComment&roi=${comment.id}" />"2 data-partial-update="click"3 data-partial-update-target="rpl${comment.id}"4 data-partial-update-settings="{ "requestTarget": "addPostArea", "alterHistory": false, "suppressRedirect": "false", "exceptParams": ["objectId","objectType","referencedObjectId","referencedObjectType"] }"5>6 <a href="#">${rjf.label('reply')}</a>7 <blockquote>${comment.text}</blockquote>8</div>
tecnické detaily - z obecné dokumentace
Libovolnou RamJet komponentu (nebo více komponent) je možné si nechat serverem vykreslit samostatně bez ohledu na zbytek stránky. Stačí k tomu sestavit správně URL následujícím způsobem:
1 /qf/jazyk/modul/cesta/ke/strance@idKomponenty2/qf/jazyk/modul/cesta/ke/strance@idKomponentyA+idKomponentyB
Server následně vrátí pouze HTML odpovídající daným komponentám, které jse možné na klientu vyměnit bez kompletní reinicializace celé stránky.
Zkopírovat odkaz na sekcihttp hlavičky a suppressRedirect
Funkcionalita umožnuje nahradit 302 redirect za mechanizmus, kdy server pouze odešle http hlavičku (FULL_PAGE_REDIRECT) a klient zpracuje výstup této stránky, pokud je v ní cílová komponenta dostupná.
Partial update pracuje dále s těmito hlavičkami
| Http hlavička | popis |
|---|---|
| FULL_PAGE_REDIRECT | Vyžadováno ve chvíli, kdy klient požádá o AJAX partial update výměnu stránky, ale server rozhodne o přesměrování na strukturálně jinou stránku, vůči které není možné partial update provést. Např. chci si vyměnit select a server místo toho rozhodne, že vypršela session a potřebuje fullscreen přesměrovat na login page. |
| RamJet-RequestedUrl | Vyžadováno pro správné fungování partial update - pokud server provede přesměrování přes HTTP302 a tudíž naviguje na odlišnou URL, klient se o této nové URL z API XmlHttpRequestu nedozví (je tam auto-follow redirects). Skrze tuto hlavičku dokážeme informovat JS o správné aktuální URL, se kterou má nadále pracovat. |
| RamJet-RequestedParameters | Souvisí s hlavičkou RamJet-RequestedUrl - slouží k přenosu vstupních parametrů z Query stringu. |
| RamJet-Error | Signalizuje validační chybu / chybu vykonání akce ('true' pokud je chyba). Slouží pro JS, aby např. detekoval tuto situaci a nezavřel aktuálně otevřený popup apod. |
Zkopírovat odkaz na sekciZákladní chování je následující
TODO revize
- pokud dojde k submitu formuláře na stejnou stránku, dojde pouze k AJAXové výměně dat a náhradě obsahu celého jsPartialUpdate
- pokud dojde ke kliknutí na odkaz uvnitř jsPartialUpdate a odkaz směřuje na stejnou stránku, dojde pouze k AJAXému načtení dat a částečné výměně obsahu bez reinicializace stránky
- pokud dojde ke kliknutí na odkaz uvnitř jsPartialUpdate a zároveň uvnitř HTML formuláře a odkaz směřuje na stejnou stránku, posbírají se aktuální data z formuláře, spojí se s parametry linku a vše se odešle AJAXem na server a vrácená odpověď se v obsahu vymění bez reinicializace stránky
Platí pravidlo, že pokud není řečeno jinak, vyměňuje se vždy celý obsah jsPartialUpdate komponenty. Server zpracovává požadavek na částečné přenačtení stránky úplně stejně jako každý jiný požadavek. Tj. jsou standardně spouštěna všechna přerušení, konverze, validace, akce - vyjímkou je pouze zpracování "render" fáze, kdy dojde k vykreslení pouze části komponent a ne celé stránky. Toto je velmi důležité si uvědomit, především kvůli správě paměti na straně serveru - tj. u stránek, které si na straně serveru neudržují žádná data, musíme vždy poslat všechny parametry nutné k jejich správnému fungování.