Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno [JS, jQuery, AngularJS] prebliknutie pri načitávaní

Zdravím,

potrebujem poradiť s problémom:

index.html:


<body data-ng-app="app" data-ng-cloak="">
    ...
    <div data-ng-view=""></div>
    ...
</body>

view.html:


    ...
    <span data-ng-bind="vysledok"></span>
    text ktorý preblikne
    ...
    <span data-ng-bind="vysledok2"></span>
    ďalší text ktorý preblikne
    ...

app.js:


/* routing */
...
$routeProvider.when('/mojaurl',  {
    templateUrl: 'view.html',
    controller: 'myctrl'
})
...

...
app.controller('myctrl', function($scope) {
    $scope.vysledok = ... ;
    ...
    ...
    $scope.vysledok2 = ... ;
}

jak môžem tomu preblikávaniu zabrániť? Zatial som to riešil spôsobom že som mal skrz CSS skrytý obsah ktorý preblikával a potom skrz jQuery .show() som ho zobrazil, ale když je toho obsahu tucet rôznak zanestovaný a propletený obsahom ktorý sa binduje tak je to problém. Veľkosť elementov nemôžem nastaviť napevno lebo neviem aký bude ich obsah kým to nenabindujem.

Předmět Autor Datum
Co takhle použít direktivu ng-if s vhodnou podmínkou, ve smyslu dokud nemám výsledek, má hodnotu fal…
Pavel 02.10.2018 20:10
Pavel
dík, skusím, i když si myslím že to je pak riešenie skoro totožné s riešením v jQuery, a pre každý t…
Mlocik97 02.10.2018 20:24
Mlocik97
tak problém to nevyriešilo, stále preblikávanie. a stejné je to aj v prípade show. Docela nechápem ž…
Mlocik97 02.10.2018 20:41
Mlocik97
Jo a je divný, že tahle rada nepomohla. Dals to opravdu přímo do hlavičky do tagu style?
Pavel 02.10.2018 20:14
Pavel
ano dal...
Mlocik97 02.10.2018 20:23
Mlocik97
Co tohle?
Pavel 02.10.2018 20:44
Pavel
AngularJS načitávam v heade ešte pred funkcemi kde do $scope priraďujem dáta. Skôr ma napadlo že do…
Mlocik97 02.10.2018 20:48
Mlocik97
problém vidím asi v tomto: [qamRKkx.png] tretí a paty riadok v screenshote sú súbory s dátami ktor…
Mlocik97 02.10.2018 20:54
Mlocik97
Co teda to obejít takto? Při spuštění aplikace (načtení webu) se zobrazí jen prázdná stránka (nebo s…
Pavel 02.10.2018 21:14
Pavel
skusil som to ešte trocha iným spôsobom, ktorý funguje tak trocha opačne, pri bežnom načitávaní to f…
Mlocik97 02.10.2018 21:19
Mlocik97
Tak teď už ti vůbec nerozumím.
Pavel 02.10.2018 21:23
Pavel
Predstav si takú situáciu že pôvodne sa mi to načitávalo takto (hviezdička predstavuje začiatok riad…
Mlocik97 02.10.2018 21:30
Mlocik97
Jo, už chápu. Zkus teda prvně zobrazit prázdnou stránku a po načtení dat z AJAX volání přes routerPr…
Pavel 02.10.2018 21:40
Pavel
No jasně že má!
Pavel 02.10.2018 21:43
Pavel
pozerám toto by mohlo byť asi najlepšie riešenie.
Mlocik97 02.10.2018 21:58
Mlocik97
tak to nechápem, ale i s týmto kódom: resolve: { app: function($q) { var defer = $q.defer(); defer… poslední
Mlocik97 02.10.2018 22:21
Mlocik97
<span ng-if="loaded && step > 0">Tohle jako první</span><span ng-if="loaded && step > 1">Tohle jako…
Pavel 02.10.2018 21:29
Pavel
Dík, skúsil som to a funguje to. Akurát mi to prijde trocha nepraktické. To už pak neni lepšie volať…
Mlocik97 02.10.2018 21:39
Mlocik97
Myslím že tá premenná counter pak zbytočne bere výkon i zaberá RAM protože mám o premennú navyše. T…
Pavel 02.10.2018 21:41
Pavel
Tak som to nakoniec vyriešil ešte úplne inak, riešením ktoré sa mi docela páči. Postupnosť načitáva…
Mlocik97 02.10.2018 21:50
Mlocik97
A můžeš sem to řešení vložit? Díky.
Pavel 02.10.2018 21:52
Pavel
.then(function() { $scope.vysledok1 = ...; $(el).eq(0).show(); $scope.vysledok2 = ...; $(el).eq(1).s…
Mlocik97 02.10.2018 21:57
Mlocik97
.then() je promise (pokud se tedy nepletu); ty proměnný co máš ve $scope nemají nastavenu výchozí ho…
Pavel 02.10.2018 21:21
Pavel
áno je to promise. $scope nemajú nastavenú výchozí hodnotu. Skusim to ale nemyslím že to pomôže, keď…
Mlocik97 02.10.2018 21:26
Mlocik97

tak problém to nevyriešilo, stále preblikávanie. a stejné je to aj v prípade show. Docela nechápem že direktívy sa v HTML nevykonávajú postupne. Lebo bind sa použije až po tom čo sa použije if alebo show ktorý je o 3 riadky nižšie.

AngularJS načitávam v heade ešte pred funkcemi kde do $scope priraďujem dáta. Skôr ma napadlo že do toho $scope sa tie dáta dostanú pozdejšie než AngularJS usúdi že stránku celú vyparsoval a že môže odstrániť styly pre ng-cloak... skusil som dať ručne do CSS display none pre práve tieto elementy a dať na tie elementy direktívu jak show tak if s hodnotou true, v oboch prípadoch sa zobrazilo cca o 60ms skôr než sa dáta nabidnovali.

problém vidím asi v tomto:

[qamRKkx.png]

tretí a paty riadok v screenshote sú súbory s dátami ktoré sa používajú pre výpočet výsledku ktorý sa binduje. P.S. asi som mal zmíniť že dáta ktoré priraďujem do $scopu a následne sa bindujú že sú vnorené vo funkcii ktorá sa volá po dokončení predchádzajúcej funkcii (AJAX requestu)... asi tým že používam .then() to asi taky neco delá, lenže inak než s tým .then() to nemá ako spraviť.

Co teda to obejít takto? Při spuštění aplikace (načtení webu) se zobrazí jen prázdná stránka (nebo stránka s obyč. textem, něco ve smyslu placeholder) a přes časovací funkci setTimeout() se nastaví zavolání požadované stránky, tj. změní se programově adresa v $routeProvider třeba za 100ms?

skusil som to ešte trocha iným spôsobom, ktorý funguje tak trocha opačne, pri bežnom načitávaní to funguje super, pri pomalom načitávaní rádovo pri rýchlostiach slow 3G tak vidno prebliknutie teraz tak že sa dáta nabindujú ešte skorej než sa zobrazí ten text ktorý už v HTML bol, čož je opak toho čo som teraz riešil. Spôsobilo to to že za funkcí kde jsem vykonával výpočet výsledku pre binding tak som použil .then(function() {$scope.loaded = true}; a pak som všade do if direktív napcal loaded hodnotu. Neviem jak to ale spraviť tak aby sa to presne postupne načítalo. Resp prvý binding, zobrazenie textu za ním, druhý binding za prvým textom, zobrazenie textu za druhým bindingom. atd.

Predstav si takú situáciu že pôvodne sa mi to načitávalo takto (hviezdička predstavuje začiatok riadku):

prvá snímka:


*
*neco
*
*

druhá snímka:


*bindované dáta
*ďalšie bindované dáta
*neco
*

tretia snímka:


*bindované dáta
*ďalšie bindované dáta
*neco
*a ďalšie bindované dáta

jak vidíš text "neco" bylo skorej na druhom riadku, potom na tretom, pretože bindované dáta to odsunuli, keďže to neco v prvej snímke na druhom riadku bolo vykreslené len asi 60ms, tak to vyzeralo ako prebliknutie.
po mojom pokuse o riešení:

prvá snímka:


*bindované dáta
*ďalšie bindované dáta
*
*

druhá snímka:


*bindované dáta
*ďalšie bindované dáta
*a ďalšie bindované dáta
*

tretia snímka:


*bindované dáta
*ďalšie bindované dáta
*neco
*a ďalšie bindované dáta

Jo, už chápu. Zkus teda prvně zobrazit prázdnou stránku a po načtení dat z AJAX volání přes routerProvider změnit url a tím načíst tvou stránku - pokud teda ten AJAX neprobíhá v controlleru.

Ještě mě napadlo: nemá Angular něco jako resolve? Ve smyslu "dokud nemám data, nedojde k zobrazení stránky"?

<span ng-if="loaded && step > 0">Tohle jako první</span><span ng-if="loaded && step > 1">Tohle jako druhé</span>

V tom volání AJAXu si vždy ve funkci co je uvnitř .then() nastavíš hodnotu proměnné step. Provede se první volání AJAX a vrátí se výsledek, nastavím step = 1; provede se druhý volání AJAX a vrátí se výsledek, nastavím step = 2.

A je to :-)

Dík, skúsil som to a funguje to. Akurát mi to prijde trocha nepraktické. To už pak neni lepšie volať rovno funkci show() na oindexované elementy, teda že bych tým elementom nastavil class="i/* číslo */"? Myslím že tá premenná counter pak zbytočne bere výkon i zaberá RAM protože mám o premennú navyše. Nakoniec to vyzerá že zostanem pri starom riešení. Resp. ani nemusím nastavovať tie classy. Využijem pseudo selector nth-type-of.

.then(function() {
    $scope.vysledok1 = ...;
    $(el).eq(0).show();
    $scope.vysledok2 = ...;
    $(el).eq(1).show();
    ...
})

Je to riešenie docela blízko mojmu pôvodnému (to riešenie som však nechcel kvôli tomu že boli elementy rôzne zanestované, avšak funkce eq() nepočíta poradie el v určitom elemente jako nth-neco selectory a pod. takže viem "počítať poradie" aj skrz rôznak zanestované elementy. Ostatne stále je to riešenie možno nie najlepšie.

.then() je promise (pokud se tedy nepletu); ty proměnný co máš ve $scope nemají nastavenu výchozí hodnotu v controlleru? Třeba na null, na prázdnej řetězec, ...?

Mimochodem: používáš $scope, tj. způsob Angularu před verzí 1.3 - ten přinesl this. Vyhovuje ti to tak? Dnes je to už velmi archaický.

áno je to promise. $scope nemajú nastavenú výchozí hodnotu. Skusim to ale nemyslím že to pomôže, keďže prebliknutie je spôsobené skôr tým že nabindovaný obsah "posunie" obsah za ním, a problém je že ja neviem "koľko" toho bindujem, a na akú výšku sa to zobrazí.

Zpět do poradny Odpovědět na původní otázku Nahoru