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… nový
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 ž… nový
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... nový
Mlocik97 02.10.2018 20:23
Mlocik97
Co tohle? nový
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… nový
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… nový
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… nový
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… nový
Mlocik97 02.10.2018 21:19
Mlocik97
Tak teď už ti vůbec nerozumím. nový
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… nový
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… nový
Pavel 02.10.2018 21:40
Pavel
No jasně že má! nový
Pavel 02.10.2018 21:43
Pavel
pozerám toto by mohlo byť asi najlepšie riešenie. nový
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… nový
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ť… nový
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… nový
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… nový
Mlocik97 02.10.2018 21:50
Mlocik97
A můžeš sem to řešení vložit? Díky. nový
Pavel 02.10.2018 21:52
Pavel
.then(function() { $scope.vysledok1 = ...; $(el).eq(0).show(); $scope.vysledok2 = ...; $(el).eq(1).s… nový
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… nový
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ď… nový
Mlocik97 02.10.2018 21:26
Mlocik97

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ý ten text budem musieť nastavovať osobitne true podmienku pre if.

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"?

pozerám toto by mohlo byť asi najlepšie riešenie.

tak to nechápem, ale i s týmto kódom:


resolve: {
			app: function($q) {
				var defer = $q.defer();
				defer.resolve();
				return defer.promise;
			}
		}

to preblikáva... asi sa s tým ešte musím pohrať, zrejme chybu niekde robím ja.

<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.

Tak som to nakoniec vyriešil ešte úplne inak, riešením ktoré sa mi docela páči.

Postupnosť načitávania som zaistil tým že som namiesto toho kde bych psal "counter++" tak som využil funkcie eq(), funguje to dokonale.

.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