[SOLVED] How to restart a find if the time is zero

Good morning, everyone,

I thank everyone who will help me! (Excuse me for my bad English)

So, I have an html table in which I display data in a loop.
This table contains 3 columns, “rows”, “destination”, “departure in…”.

In the “rows” column, I display the row number of a vehicle.
In the column “destination” I display the name of the destination of the vehicle.
In the column “departure in…” I display the departure time of the vehicle.

To display a time countdown, I use the “Depart” collection and the “heureApplicableDepart” field with this coutndown http://hilios.github.io/jQuery.countdown/.

Here is the code:

imports/ui/pages/horaire.html :

<template name="horaire">
    <div class="body">
        <div class="grid">
            <!-- here my table with data -->
            {{#if Template.subscriptionsReady}}
                {{> departs}}
            {{/if}}
            <!-- end -->
            <div class="infos-trafic">
                <div class="head-trafic">
                    <h1>
                        <img src="/images/picto/picto-trafic-jaune.png" alt="Alerte">INFOS TRAFIC<img src="/images/picto/picto-trafic-jaune.png" alt="Alerte">
                    </h1>
                </div>
                <div class="body-trafic">
                    {{#each infostrafic}}
                        <p>{{#each ligne}}<img src="/images/picto/{{this}}.jpg" alt="{{this}}">{{/each}} {{message}}</p>
                    {{/each}}
                </div>
            </div>
        </div>
        <div class="pub">
            <p>PUBLICITE FORMAT 1830 (970) X 250px</p>
        </div>
    </div>
</template>

imports/ui/pages/horaire.js :

import '../../ui/components/departs.js';
import './horaire.html';

/**
 * onCreated
 * A la création du template horaire, s'abonner à la collection xxxx
 */
Template.horaire.onCreated(function() {
    this.subscribe('arret');
    this.subscribe('depart');
    this.subscribe('infostrafic');
});

/***
 * OnRendered
 * A la fin du rendu du template, on récupère la valeur du paramètre data-countdown qui se trouve
 * dans le tag <td data-countdown="date"></td> de notre template departs.html
 */
Template.departs.onRendered(function(){
        // Here countdown jquery
        $('[data-countdown]').each(function () {
            let $this = $(this), finalDate = Date.parse($(this).data('countdown'));
            $this.countdown(finalDate, function (event) {
                if(event.strftime('%M') <= 0) {
                    $this.html("Départ imminent");
                }else if(event.strftime('%H') >= 1) {
                    $this.html(event.strftime("%H:%M"))
                }else {
                    $this.html(event.strftime('%M min'));
                }
            });
        });

});

/**
 * Helpers
 *
 */
Template.header.helpers({
    arret: () => {
        return Arret.findOne({});
    }
});

Template.departs.helpers({
    depart: () => {
        return Depart.find({});
    }
});

Template.horaire.helpers({
    infostrafic: () => {
        return Infostrafic.find({});
    }
});

imports/ui/components/departs.html :

<template name="departs">
    <table class="horaire-arret">
        <tbody>
            <tr>
                <th>Ligne</th>
                <th>Destination</th>
                <th>Départ dans</th>
            </tr>
            {{#each depart }}
            <tr>
                <td><img src="/images/picto/{{numeroVehicule}}.jpg" alt="ligne"></td>
                <td>{{nomDestination}}</td>
                <td data-countdown="{{heureApplicableDepart}}"></td>
            </tr>
            {{/each}}
        </tbody>
    </table>
</template>

imports/ui/components/Departs.js

import './departs.html';

publish depart.js :

import moment from "moment/moment";

Meteor.publish('depart', function(numeroArret){
    let todayStart = moment().startOf('day').toDate();
    let todayEnd = moment().endOf('day').toDate();
    return Depart.find({"numeroArret" : parseInt(numeroArret), "jourExploitation" : {$lt : todayEnd, $gte: todayStart }}, {fields: {'nomArret':1, 'nomDestination':1, 'numeroVehicule':1, 'heureApplicableDepart':1, 'retard':1, 'avance':1, 'numeroArret':1}, sort : [['heureApplicableDepart', 'asc'], ['numeroVehicule', 'asc']]});
});

Collection “Depart” with an example :

Depart = new Mongo.Collection("depart");

/**
Depart.insert(
    {
        jourExploitation: new Date(),
        nomArret: 'TARN',
        numeroArret: 327,
        typeVehicule: 'C',
        heureTheoriqueDepart: new Date('2018-04-23 15:35:00'),
        heureApplicableDepart: new Date('2018-04-23 15:35:00'),
        heureRealiseArrivee: new Date('2018-04-23 15:35:00'),
        heureRealiseDepart: new Date('2018-04-23 15:35:00'),
        heureTheoriqueArrivee: new Date('2018-04-23 15:35:00'),
        heureApplicableArrivee: new Date('2018-04-23 15:35:00'),
        avance: 0,
        retard: 0,
        nomDepart: 'JONQUILLES',
        nomDestination: 'GARE CENTRALE',
        numeroVehicule: 10,
        sens: 'R',
        debutperturbation: new Date('1970-01-01 01:00:00.000'),
        finperturbation: new Date('1970-01-01 01:00:00.000')
    }
);
**/

Everything works fine. Now, when the time in the “departure in…” column is 0, I would like the line to be automatically replaced by another one that has a time greater than 0 and so on.

I was able to read things on tracker.autorun, but I don’t think it can solve the problem, I tried to use it but it didn’t work.

I can not find a solution, we still know meteorjs poorly and how it works, I am obliged to ask you for your generous help.

Thank you for everything that will help to solve my problem.

The answer probably lies here:

this.subscribe('depart');

and in the corresponding publication. I’ve simplified your publication and added a field (estParti) to simplify the explanation - you’ll want to do this differently:

Meteor.publish('depart', function() {
  return Depart.find({ estParti: false }, { sort: { heureDepart: 1 }, limit: 5 });
});

When that runs, it returns the top 5 entries of departures which are still waiting to depart.

When the top item on the client counts down to zero, you want to:

  • Set estParti to true and
  • Re-run the publication (you could set esParti as the first action in the publication to keep the code tightly coupled).

The way to re-run the publication is to re-subscribe on the client. The way to re-subscribe when something changes (the countdown), is to make the countdown a ReactiveVar or ReactiveDict and use a template autorun. This needs to be available to the horaire and departs templates. The easiest way to do that (not necessarily the best way) is to attach the ReactiveVar to the window object. So, on the client:

Template.horaire.onCreated(function() {
  window.countdownAtZero = new ReactiveVar(false); // when the countown reaches zero, we set this in the onRendered
  this.autorun(() => {
    this.subscribe('arret');
    this.subscribe('depart', window.countdownAtZero.get()); \\ getting the reactive var makes this whole part re-run on a change.
    this.subscribe('infostrafic');
  });
});

Note - arret and infostrafic will also re-run, but as they have no reactive dependency, it doesn’t cost anything. You can always move them out of the autorun if you’re worried.

In your onRendered you’ll need to window.countdownAtZero.set(true); at the appropriate time.

That’s basically it. However, as you have multiple countdowns in your departs template, you may need to refactor to use a ReactiveDict and index the appropriate entry.

Sorry if that sounds complicated - it’s easier than it seems!

Check out The Meteor Guide for more on pub/sub and the ReactiveDict package for more on ReactiveDict. :slight_smile:

1 Like

Okay, thank you very much for your help! You’re very kind. This is the third time you’ve come to my aid.

I will look at all this in more detail and put it into practice, I will keep you informed on this topic.

See you soon.

1 Like

Hello there,

Ur proposal is working perfectly! Thank you :heartpulse:

1 Like