Function while populating a table + store retrieved data (JSON) as a session or a var?

Hi,

I’m having two issues:

1st:
I’m retrieving JSON data using a HTTP.call. With the retrieved data, I’m populating a table. But during the populating of the table, another function has to be called for retrieving a new result, based on the value of a specific JSON object. This data should be retrieved from a mongoDB collection. How should I do this?

What I’m having now is:

api.js

Template.API.events({
    'submit .dosubmit': function(event) {
        event.preventDefault();
        var ID = event.target.sub.value;
        var getRows = event.target.rows.value;
        if(ID == "") {
            alert('Er is geen subscriber ID opgegeven!');
        } else {
            Session.set('disabled', 'disabled');
            console.log("Entered ID is: " + ID);
            console.log("Entered Rows is: " + getRows);
            Meteor.call('checkCalls', ID, getRows, function(error, result) {
                if(error){
                    console.log(error);
                    Session.set("JSONError", true);
                    Session.set('disabled', '');
                } else {
                   var json = JSON.parse(result.content);
                    Session.set('disabled', '');
                    Session.set("JSONResult", json._embedded['nested:array']);
                    var Calls = json._embedded['nested:array'];
                    Session.set("TotalCount", json.total_count);
                }
            });
        }
    }
});

api.html

<table class="table">
    <thead>
        <th>Call ID</th>
        <th>Caller</th>
        <th>Callee</th>
        <th>Zone</th>
        <th>Startdatum en tijd</th>
        <th>Duur</th>
        <th>Kosten</th>
    </thead>
    <tbody>
        {{#if $.Session.equals 'JSONError' true}}
            <tr>
                <td colspan="4">Fout bij ophalen van gegevens!</td>
            </tr>
        {{else}}
            {{#each $.Session.get 'JSONResult'}}
            <tr>
                <td>{{id}}</td>
                <td>{{source_cli}}</td>
                <td>{{destination_user_dialed}}</td>
                <td>{{zone_id}}</td>
                <td>{{start_time}}</td>
                <td>{{duration}}</td>
                <td>{{source_customer_cost}}</td>
            </tr>
            {{else}}
            <tr>
                <td colspan="4">Geen gegevens gevonden</td>
            </tr>
            {{/each}}
        {{/if}}
            <tr>
                <td colspan="4">Totaal aantal rijen: {{$.Session.get 'TotalCount'}}</td>
            </tr>
    </tbody>
</table>

The value in column Zone should retrieved while populating this table, based on the value of {{zone_id}}.

2nd:
As can be seen in the code from api.js above, I’m storing the result in a Session instead of a variable. I can store it in a variable, but then #each doesn’t do anything. So:

This works

{{#each $.Session.get 'JSONResult'}}

But this doesn’t

{{#each Calls}}

What is preferred in this scenario? Sessions or variables?

1st:
There are many ways of doing this depending on whether the Zone data is already published to the client and how efficient you want the process to be.

If the Zone data isn’t already published to the client, the most efficient way of doing this would be to make your checkCalls method loop through the result of the HTTP.call and append the zone data you need into the array before returning the result. That means, then as well as {{zone_id}} you also have {{zone_name}}.

If the zone data is already published to the client then you would need to insert the zone_name with a helper function like this:

api.html

<th>{{getZoneName zone_id}}</th>

api.js

Template.API.helpers({
  getZoneName(zone_id) {
    return zonesCollection.findOne({_id: zone_id}).zone_name;
  }
});

2nd:
Normal javascript variables don’t work because they are not reactive. Session variables are reactive so when you change them the UI re-renders with the new data. Instead of using Session you could consider using ReactiveVar or ReactiveDict - you can attach the ReactiveVar to the template instance and it is automatically deleted when the template is deleted, freeing memory. Read more here: https://blog.meteor.com/the-meteor-chef-reactive-dict-reactive-vars-and-session-variables-971584515a27

1 Like

Thanks for the reply.

I’m getting stuck retrieving the data from the collection.

api.js:

BillingZones = new Mongo.Collection('BillZones');

Template.API.onCreated(function setVars() {
    var self = this;
    self.autorun(function() {
        self.subscribe('BillingZones');
    });

});

Template.API.helpers({
    getZoneName(zone_id) {
      cZone = BillingZones.findOne({id: zone_id}).zone;  
      return cZone ;
    },

But this isn’t getting me the required result.

Below is an example of the JSON:

[
  {
	"tbl_id": "11",
	"id": "151491",
	"zone": "Name 1"
  },
  {
	"tbl_id": "12",
	"id": "151493",
	"zone": "Name 2"
  },
  {
	"tbl_id": "13",
	"id": "151495",
	"zone": "Name 3"
  },

e.g.:

Show the zone_id be 151495, I’d expect Name 3 to show up in the Zone column.

When going to the Mongo CLI and typing:

db.BillZones.find({"id": "151495"});

It returns:

{ "_id" : ObjectId("59ff5dd68b1b86ccfc7d564a"), "tbl_id" : "48", "id" : "151565", "zone" : "Name 3" }

Any Idea what I’m doing wrong?

Update: When trying @ the Mongo CLI:

db.BillZones.findOne({id: "151495"}).zone;

This will also return me the right zone name.

Update 2:
Fixed it by doing a

BZone = zone_id.toString();

Before doing a find. Except now I get errors in the console, when the zone_id isn’t set (which in some cases can occur).

If tried:

    getZoneName(zone_id) {
        if (zone_id != '' || zone_id != null) {
            BZone = zone_id.toString();
            return BillingZones.findOne({id: BZone}).zone;  
        }
    }

But this still results in errors in the console log. Any other ideas on how to prevent these?

It would be useful to know that the console messages are.

However, there is an obvious flaw in your logic

if (zone_id != '' || zone_id != null) {

should be

if (zone_id != '' && zone_id != null) {

or even better, just

if (zone_id) {

assuming a zone_id of zero wont exist.

Another possible error case is when the zone_id is valid but doesn’t have an entry in the BillingZones collection. In which case try:

    getZoneName(zone_id) {
        if (zone_id) {
            var BZone = zone_id.toString();
            var Zone=BillingZones.findOne({id: BZone});
            return Zone && Zone.zone;  
        }
    }

:+1: … and if anyone else is interested in understanding why this is true*, check out De Morgan’s Theorem.


* A little Boolean humour, there :wink: