Pass a async result across templates


#1

Hi guys, I get a MSSQL result in Template.cars.onCreated through async/await and callPromise and trying to pass this result to carDetails, but I get nothing but undefined in target template’s onCreated, onRendered and helpers.

If get rid of the async in Template.cars.onCreated, I am able to pass synchronous parameter even though it is a ReactiveVar.

I am wondering what kind of modification I should do for this case. All ideas are most welcome! Thanks

In cars.js

Template.cars.onCreated(async function () {
    this.reactiveSeekerData = new ReactiveVar();
    var carID= "123456";
    var self = this;
    var data = await Meteor.callPromise('MSSQLQuery', carID);
    self.reactiveCarData.set(data);
    return self.reactiveCarData.get();
    }
});

Template.cars.helpers({
    carsData:  function () {
        var instance= Template.instance();
        var data =  instance.reactiveCarData.get();
        console.dir(data); //Rusult is the correct result which is an object 
        return data;
    },
});

in cars.html

 {{> Template.dynamic template="carsDetails" data=carsData}}

in carsDetails.js

Template.carsDetails.onCreated( function() {
  var data = this.data;
  console.dir(data); //undefined
});

Template.carsDetails.onRendered( function() {
  var data = this.data;
  console.dir(data); //undefined
});

Template.carsDetails.helpers({
  exclamation: function() {
    var data = Template.instance().data;
    console.dir(data); //undefined
    return 0;
  }
});

#2

I can’t see anything obvious which would prevent that working. There are a few changes I would make for syntax and redundant code. Otherwise, given the code you’ve shared, it should work (and in my independent test, it does).


#3

Hi Rob, my friend told me the issue is the return value in the Template.cars.helpers.

var data = instance.reactiveCarData.get(); is returning a static get() value which should be replaced by
var data = instance.reactiveCarData; which is returning a reactive variable.


#4

Hmm. Your friend is misinformed: instance.reactiveCarData.get() returns a reactive value (the current value in the reactive variable); instance.reactiveCarData returns a reference to the reactive variable, not the value.

Here’s a minor reworking of your code which should work - it works for me, but I obviously don’t have access to the rest of your code. I’ve fixed the issues I mentioned and used ES6 syntax.

Template.cars.onCreated(async function () {
  this.reactiveCarData = new ReactiveVar();
  const carID= "123456";
  const data = await Meteor.callPromise('MSSQLQuery', carID);
  this.reactiveCarData.set(data);
});

Template.cars.helpers({
  carsData() {
    const instance= Template.instance();
    const data =  instance.reactiveCarData.get();
    console.dir(data);
    return data;
  },
});

in carsDetails.js

Template.carsDetails.onCreated( function() {
  const data = this.data;
  console.dir(data);
});

Template.carsDetails.onRendered( function() {
  const data = this.data;
  console.dir(data);
});

Template.carsDetails.helpers({
  exclamation() {
    const data = Template.instance().data;
    console.dir(data);
    return data;
  }
});

#5

Hi Rob, I modified my code according to your suggestion but it didn’t work.

“MSSQLQuery” returns an array of object which I can get in “cars” perfectly.

Meteor.methods({
    async MSSQLQuery(carID) {
        var sql = require('mssql');
        let config = {
            user: "user_name",
            password: "password",
            database: "CAR",
            server: "localhost"
        };
        try {
            var query = 'SELECT * FROM [car] WHERE [car].[ID]=' + carID + ';';
            var connection = await sql.connect(config);
            var result = await connection.request().query(query);
            sql.close();
            return (result);
        } catch (error) {
            sql.close();
            return (error.message);
        }
    }
})

Now I have a workaround that I use Session to replace passing ReactiveVar across those templates. I know it may be not a wise choice but I still have no much confidence in Blaze template’s value passing. Thanks.