0

I'm working on a project to manage the attendance of students in school.

The frontend runs with meteor. It displays the presence of all students from one class for the current day. The user (teacher) can switch the days back and forth, to make some changes.

Now I'm wondering how to rerun the helpers function for presentStudents when the selectedDate is changed.

The html code:

<head>
    <meta charset='utf—8' name='theme—color' content='#282A36'>
    <title>Anwesenheit</title>
    <!-- This website includes -->
    <link href='https://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet' type='text/css'>
    <!-- Currently not in use but later needed to get nice icons for the buttons to switch between the dates. -->
    <script defer src='https://use.fontawesome.com/releases/v5.0.2/js/all.js'></script>
</head>

<body>
    <header class=''>
        <div class='heading'>Anwesenheitliste</div>
    </header>

    <div class='backboard'>
        <header class=''>
            <div id='search_space'>
                <form class='insertStudent'>
                    <input id='beacon_input' type='text' name='beacon' placeholder='Input beacon ID' autocomplete='off'>
                    <input type='submit' style='display: none'>
                </form>
            </div>
            <div id='date_space'>
                <i id='previous_date' class='fas fa-angle-left date_space_content previousDateClick'></i>
                <div id='current_date' class='date_space_content'></div>
                <i id='next_date' class='fas fa-angle-right date_space_content nextDateClick'></i>
            </div>
        </header>
    </div>

    <content>
        <div class='backboard'>
            <div class='pagecontent'>
                <div id='cat_list' class=''>
                    <table id='list' class='list_students'>
                        <tr>
                            <!--
                            <th class='cnt'>Nr.</th>
                            -->
                            <th>Vorname</th>
                            <th>Nachname</th>
                            <th>Beacon ID</th>
                            <th>1. Block</th>
                            <th>2. Block</th>
                            <th>3. Block</th>
                            <th>4. Block</th>
                        </tr>
                        {{#each presentStudents}}
                            {{> listingPresence}}
                        {{/each}}
                    </table>
                </div>
            </div>
        </div>
    </content>
</body>

<template name='listingPresence'>
    <tr>
        <td>{{firstName}}</td>
        <td>{{lastName}}</td>
        <td>{{beaconID}}</td>
        <td class='{{#if checked}}checked{{/if}}'>
            <input type='checkbox' id='{{checkbox1}}' checked='{{block1}}' class='toggled1'>
            <label for='{{checkbox1}}'>1. Block</label>
        </td>
        <td class='{{#if checked}}checked{{/if}}'>
            <input type='checkbox' id='{{checkbox2}}' checked='{{block2}}' class='toggled2'>
            <label for='{{checkbox2}}'>2. Block</label>
        </td>
        <td class='{{#if checked}}checked{{/if}}'>
            <input type='checkbox' id='{{checkbox3}}' checked='{{block3}}' class='toggled3'>
            <label for='{{checkbox3}}'>3. Block</label>
        </td>
        <td id='myCheckBox' class='{{#if checked}}checked{{/if}}'>
            <input type='checkbox' id='{{checkbox4}}' checked='{{block4}}' class='toggled4'>
            <label for='{{checkbox4}}'>4. Block</label>
        </td>
    </tr>
</template>

The code from the server/main.js:

import { Meteor } from 'meteor/meteor';

const PresenceDB = new Mongo.Collection('studentsPresence');
const ListDB = new Mongo.Collection('studentsList');


function getDate(){
    let d = new Date();
    return d.getFullYear() + ('0' + (d.getMonth() + 1)).slice(-2).toString() + d.getDate().toString().slice(-2);
}

export function init(){
    const date = getDate();
    const match = PresenceDB.find({date: date}).fetch();
    if(match[0] == null) {
        const allStudents = ListDB.find().fetch();
        for (const student of allStudents){
            PresenceDB.insert({
                _id: newObjectID = new Mongo.ObjectID(),
                beaconID: student.beaconID,
                firstName: student.firstName,
                lastName: student.lastName,
                block1: false,
                block2: false,
                block3: false,
                block4: false,
                checkbox1: newObjectID1 = new Mongo.ObjectID(),
                checkbox2: newObjectID2 = new Mongo.ObjectID(),
                checkbox3: newObjectID3 = new Mongo.ObjectID(),
                checkbox4: newObjectID4 = new Mongo.ObjectID(),
                date: date
            });
        }

    }
}


Meteor.startup(() => {
    // code to run on server at startup
    init();
});

The code from the client/main.js:

import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
// When this is imported the website doesn't load anymore!
//import { Session } from 'meteor/session';

import './main.html';

// Declare used collections
const PresenceDB = new Mongo.Collection('studentsPresence');
const ListDB = new Mongo.Collection('studentsList');

let selectedDate = getDate(0);

window.onload = function () {
    document.getElementById('current_date').textContent = getDate(1);
};

Date.prototype.addDays = function (n) {
    alert('Function got called!');
    let year = Number(selectedDate.slice(0, 4));
    let month = Number(selectedDate.slice(4, 6));
    let day = Number(selectedDate.slice(6, 8));
    if((day + n) > daysInMonth(month, year)) {
        month++;
        if(month < 1) {
            month = 12;
            year--;
        } if(month > 12) {
            month = 1;
            year++;
        }
        day = 0;
    }
    if((day + n) < 1) {
        month--;
        if(month < 1) {
            month = 12;
            year--;
        } if(month > 12) {
            month = 1;
            year++;
        }
        day = daysInMonth(month, year);
    } else {
        day = day + n;
    }
    document.getElementById('current_date').textContent = ('0' + day).slice(-2) + '.' + ('0' + month).slice(-2) + '.' + year;
    return '' + year + ('0' + month).slice(-2) + ('0' + day).slice(-2);
};

// Function for getting the number of days for a month depending on the month and year
function daysInMonth(month, year) {
    return new Date(year, month, 0).getDate();
}

// Function for getting today's date in the right format
function getDate(n){
    let d = new Date();
    if(n === 0) {
        // Return the date in the format: YYYYMMDD
        return d.getFullYear() + ('0' + (d.getMonth() + 1)).slice(-2).toString() + d.getDate().toString().slice(-2);
    } else {
        // Return the date in the format: DD.MM.YYYY
        return d.getDate().toString().slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2).toString() + '.' + d.getFullYear();
    }
}

// Function for getting right time in the right format
function getTime(){
    let t = new Date();
    const time = t.getHours().toString() + t.getMinutes().toString();
    return parseInt(time, 10);
}

// Function to determine the current block lesson
function getBlock(time){
    let block = 0;
    if (745 < time && time < 915){
        block = 1;
    } else if (915 < time && time < 1100){
        block = 2;
    } else if (1100 < time && time < 1245){
        block = 3;
    } else if (1245 < time && time < 1800){
        block = 4;
    }
    return block;
}

// List students that are present today
Template.body.helpers({
    presentStudents: function() {
        //return PresenceDB.find({date: reactiveDate});
        return PresenceDB.find({date: selectedDate});
        //return PresenceDB.find({date: Session.get('sessionDate')});
    }
});

Template.body.events({
    // Update the presence for a scanned student for a specific lesson or create the document if necessary
    'submit .insertStudent': function(event) {
        const time = getTime();
        const currentBlock = getBlock(time);
        const userInput = event.target.beacon.value;
        const scannedStudent = ListDB.find(
            {beaconID: userInput},
            {firstName: 1, lastName: 1}
        ).fetch();
        const inPresenceList = PresenceDB.find(
            {beaconID: userInput, date: selectedDate},
            {_id: 1}
        ).fetch();
        let isExisting = (inPresenceList[0] != null);
        if (currentBlock !== 0){
            if (!isExisting){
                PresenceDB.insert(
                    {
                        _id: newObjectID = new Mongo.ObjectID(),
                        beaconID: userInput,
                        firstName: scannedStudent[0].firstName,
                        lastName: scannedStudent[0].lastName,
                        block1: false,
                        block2: false,
                        block3: false,
                        block4: false,
                        checkbox1: newObjectID1 = new Mongo.ObjectID(),
                        checkbox2: newObjectID2 = new Mongo.ObjectID(),
                        checkbox3: newObjectID3 = new Mongo.ObjectID(),
                        checkbox4: newObjectID4 = new Mongo.ObjectID(),
                        date: selectedDate
                    });
                const currentBlockString = 'block' + currentBlock;
                let obj = {};
                obj[currentBlockString] = true;
                PresenceDB.update(
                    {_id: newObjectID},
                    {$set: obj}
                );
            } else {
                const currentBlockString = 'block' + currentBlock;
                let obj = {};
                obj[currentBlockString] = true;
                PresenceDB.update(
                    {_id: inPresenceList[0]._id},
                    {$set: obj}
                );
            }
        } else {
            alert('Außerhalb der Schulzeiten!');
        }
        event.target.beacon.value = '';
        return false;
    },
    'click .previousDateClick': function(event) {
        //changeDate(0);
        let d = new Date();
        //selectedDate = d.addDays(0);
        Session.set('sessionDate', d.addDays(0));
        Session.set('sessionDate', 'TestSenf');
        alert(Session.get('sessionDate'));
    },
    'submit .nextDateClick': function(event) {
        //changeDate(1);
        let d = new Date();
        selectedDate = d.addDays(1);
        Session.set('sessionDate', selectedDate);
    }
});

Template.listingPresence.helpers({
    /*presentStudents: function() {
        // Here we get our template instance from Template.instance() and
        // can access showExtraFields from it.
        return Template.instance().reactiveDate.get();
    }*/
});

Template.listingPresence.onCreated(function(){
    // Here, this equals the current template instance. We can assign
    // our ReactiveVar to it, making it accessible throughout the
    // current template instance.
    this.reactiveDate = new ReactiveVar( selectedDate );
});

Template.listingPresence.events({
    'click .toggled1': function() {
        PresenceDB.update(this._id, { $set: {block1: !this.block1}})
    },
    'click .toggled2': function() {
        PresenceDB.update(this._id, { $set: {block2: !this.block2}})
    },
    'click .toggled3': function() {
        PresenceDB.update(this._id, { $set: {block3: !this.block3}})
    },
    'click .toggled4': function() {
        PresenceDB.update(this._id, { $set: {block4: !this.block4}})
    }
});
Jub
  • 1
  • 5
  • Do you have an event handler for when data is changed? If so, you can assign the new date to a session (as they're reactive). So Session.set('selectedDate', ..). Then your helper, can be updated so that 'return PresenceDB.find({date: Session.get('selectedDate')});' – Mo A Jan 22 '19 at 11:53
  • I got no such thing right now. I just found out about **Reactive Vars** and currently I'm trying to work with those. Do i need to specify the `Session.set('selectedDate', YYYYMMDD);` within the `Template.body.events({});`? – Jub Jan 22 '19 at 12:20
  • That's right, you set your Session within `Template.body.events({..})`, upon the user changing the `selectedDate` – Mo A Jan 22 '19 at 12:26
  • Okay. But in what format do I need to insert it into the `Template.body.events({})`? I'm changing the date with font-of-awesome icons. With an onload function `window.onload = function () {document.getElementById('previous_date').onclick = function() {changeDate(0);};document.getElementById('next_date').onclick = function() {changeDate(1);};};` – Jub Jan 22 '19 at 12:31
  • You can follow the Meteor tutorial on events - https://www.meteor.com/tutorials/blaze/forms-and-events. – Mo A Jan 22 '19 at 12:41
  • Thanks a lot! If I understand it correctly I need to move the functions from the onload / onclick into the `Template.body.events({});` using an event like submit? – Jub Jan 22 '19 at 12:56
  • Yes, that's correct. Then when you assign the date to a Session, the `presentStudents` helper will rerun when the date is changed. – Mo A Jan 22 '19 at 12:59
  • Okay nice. I got that event part working. But somehow is `Session.set('sessionDate', d.addDays(0));` not calling the function **addDays(n)**. Am I missing something? – Jub Jan 22 '19 at 13:39
  • Just ensure `addDays(0)` actually returns a value. Would help if you update the question with the function and code. – Mo A Jan 22 '19 at 13:46
  • Okay I've uploaded most of my code here. I think I need to import Session into the client/main.js. But if I do so: The website loads displaying nothing. – Jub Jan 22 '19 at 14:31
  • I got it running now! Thanks a lot for your help, it's much appreciated! – Jub Jan 22 '19 at 15:08
  • Glad it worked! – Mo A Jan 22 '19 at 15:10

0 Answers0