{{...">
    All geek questions in one place

    Meteor: until all patterns are displayed

    I have the following template code

    <template name="home"> <div class="mainBox"> <ul class="itemList"> {{#each this}} {{> listItem}} {{/each}} </ul> </div> </template> <template name="listItem"> <li class="item"> {{username}} </li> </template> 

    And I would like to execute the code as soon as ALL of the "listItem" are rendered. There are about 100 of them. I tried the following

     Template.home.rendered = function() { // is this called once all of its 'subviews' are rendered? }; 

    But this does not wait for the download of all views.

    What's the best way to find out when all subtask templates load?

    +6
    javascript meteor
    ericbae 10 sept. '14 at 13:10
    source share
    5 answers

    This is how I continue:

    client/views/home/home.html

     <template name="home"> {{#if itemsReady}} {{> itemsList}} {{/if}} </template> <template name="itemsList"> <ul> {{#each items}} {{> item}} {{/each}} </ul> </template> <template name="item"> <li>{{value}}</li> </template> 

    client/views/home/home.js

     Template.home.helpers({ itemsReady:function(){ return Meteor.subscribe("items").ready(); } }); Template.itemsList.helpers({ items:function(){ return Items.find(); } }); Template.itemsList.rendered=function(){ // will output 100, once console.log(this.$("li").length); }; 

    lib/collections/items.js

     Items=new Mongo.Collection("items"); 

    server/collections/items.js

     insertItems=function(){ var range=_.range(100); _.each(range,function(index){ Items.insert({value:"Item "+index}); }); }; Meteor.publish("items",function(){ return Items.find(); }); 

    server/startup.js

     Meteor.startup(function(){ Items.remove({}); if(Items.find().count()===0){ insertItems(); } }); 

    We indicate that we want to display our list of positions only if the publication is ready, so by this time the data will be available, and the correct number of li elements will be displayed in the callback processed by the list.

    Now the same with the iron:router waitOn :

    client/views/home/controller.js

     HomeController=RouteController.extend({ template:"home", waitOn:function(){ return Meteor.subscribe("items"); } }); 

    client/lib/router.js

     Router.configure({ loadingTemplate:"loading" }); Router.onBeforeAction("loading"); Router.map(function(){ this.route("home",{ path:"/", controller:"HomeController" }); }); 

    client/views/loading/loading.html

     <template name="loading"> <p>LOADING...</p> </template> 

    Using iron:router is probably better because it elegantly solves the general pattern: we no longer need the itemsReady helper, the home pattern will only be displayed when the WaitList returned by waitOn is globally ready.

    Do not forget to add both the download template and set the default "download", otherwise it will not work.

    +3
    saimeunt 10 sept. '14 at 15:39
    source share

    I had the same problem when I had to wait for all my subtopics to load before calling the JavaScript plugin for the carousel (or any cool JavaScript plugin like charts or graphs that need the whole dataset loaded in the DOM before call him).

    I solved this by simply comparing the rank of the subtopic with the total counter that should be returned for any request I made. Once the rank is equal to the score, you can call your plugin from the subtemplate.rendered , because all subtopics have been inserted into the DOM. So in your example:

     Template.listItem.rendered = function() { if(this.data.rank === ListItems.find({/* whatever query */}).count()) { console.log("Last item has been inserted into DOM!"); // Call your plugin $("#carousel").owlCarousel({ // plugin options, etc. }); } } 

    Then you just need your helper for listItems to return the rank, which is simple enough:

     Template.home.helpers({ listItems: function() { return ListItems.find({/* whatever query */}).map(function(listItem, index) { listItem.rank = index + 1; // Starts at 1 versus 0, just a preference }); } } 
    +1
    evolross Oct 23 '14 at 1:33
    source share

    method performed in this way

    This callback is called once when the Template.myTemplate instance is mapped to DOM nodes and placed into the document for the first time.

    therefore, when rendering, you do not have a reactive variable in this case.

     // this would sufficient Template.listItem.helpers = function() { username:function(){ return ... } }; 
    0
    Walter zalazar 10 sept. '14 at 13:46
    source share

    I would suggest something like:

     var unrendered = []; Template.listItem.created = function () { var newId = Random.id(); this._id = newId; unrendered.push(newId); }; Template.listItem.rendered = function () { unrendered = _.without(unrendered, this._id); if (!unrendered.length) { // WHATEVER NEEDS DOING WHEN THEY'VE ALL RENDERED } }; 

    CAVEAT

    This works under the assumption that essentially all instances of the templates will be created before the first ones are displayed, otherwise your code will be run before it is executed. I think this should be the case, but you will have to try, since I do not have time to run the test on more than 100 templates. If this is not so, then I can’t understand how you can achieve this behavior without knowing in advance how many subatmaps will be created.

    If you know how much will be, then the code above can be simplified to a counter, which decreases every time rendered is rendered , and this is easy.

     unrendered = [number of listitems]; Template.listItem.rendered = function () { unrendered--; if (!unrendered) { // WHATEVER NEEDS DOING WHEN THEY'VE ALL RENDERED } }; 

    In addition, you may need meteor add random , but I think this package is now included in the kernel.

    0
    richsilv 10 sept. '14 at 2:04
    source share

    There are apparently various ways to deal with your situation. You can easily use template subscriptions.

     Template.myView.onCreated(function() { var self = this; self.autorun(function(){ self.mySub = self.subscribe('mySubscription'); }); if(self.mySub.ready()) { // my sweet fancy code... } }); <template name="myTemplate"> <ul> {{#if Template.subscriptionsReady}} {{#each items}} <li>{{item}}</li> {{/each}} {{else}} <div class="loading">Loading...</div> {{/if}} </ul> </template> 
    0
    Mushangi derrick Aug 6 '15 at 18:18
    source share

    Source: https://habr.com/ru/post/975065/

    More articles:

    • TypeScript: an implicit number to enumerate - casting
    • Is it possible to serialize an array at the root of an object using JMS Serializer? - json
    • Focusing WebView after closing MessageDialog - c #
    • sqlite database is OK, but jdbc reports that the database disk image is incorrect - sqlite
    • Strange cursor placement in modal mode when using autofocus in Internet Explorer - angularjs
    • https://translate.googleusercontent.com/translate_c?depth=1&rurl=translate.google.com&sl=ru&sp=nmt4&tl=en&u=https://fooobar.com/questions/975066/spring-data-jpa-repositories-is-it-possible-to-give-the-params-a-default-value-default-all&usg=ALkJrhiZu8QXBl7L5MJTtNF7zx5rd2mEcg
    • Logging in to Phantomjs, redirecting and displaying the page after the Load page completes - phantomjs
    • Where to find php_imagick.dll for php 5.5.12 for windows wampserver 2.5? - php
    • Changing swappiness for docker container - linux
    • GitHub Webhook Secret never checks - git

    All Articles

    Geek Questions | 2019