I’ve just tried a few things and Googled a few searches, but haven’t gotten anywhere…
Specifically I want to pass some Stripe invoices into a template of my app. These invoices don’t come from the db, but from an API call to Stripe. The data is returned as json. Ideally I’d just be rendering this data within the template using {{#each invoices }}. Reactivity isn’t important in this case, but is always nice to maintain.
If I use the publish/subscribe method - how do I go about it? (I’ve looked for examples that don’t involve a database collection and can’t find any) - the only way I’ve set up publish/subscribe relationships is pretty reliant on there being a db collection. I’ve had a quick go trying to use methods, helpers etc. But haven’t really gotten anywhere - and rather than making something work I figured it’s best to check what the preferred method is.
tl;dr: How do I make arbitrary json available to a template, and where do I fetch it?
The easiest way would be to make the call to Stripe, and store the invoices to a local collection (whether to do this through a cron job or pressing some button, that’s up to you). Then all you need to do is subscribe to that collection and it will be available to your template.
You could also do it through calling a Meteor.method, that calls the Stripe API and returns the json data in the callback.
Hm, that’s an interesting option actually, however due to the frequency in which I expect users to access this data it made more sense (to me) to avoid the overhead of storing the data, and to instead deal with the short delay involved in fetching the invoices on the fly.
With regards to using a method - I did have a quick go at this but I’m not really sure how it fits into the workflow. i.e. Where do I call the method from? Router? Helper? I’ve only really used methods to action something, not retrieve and display data.
Pay attention that I run this method only on server, without a stub, to avoid cross-server api calls.
In my example I call it once in onCreated as Github there’s no need for readme data to be reactive. But you can call it in autorun, a helper (make sure this helper actually gets initialized in your html) or in a click button action.
Sorry @brajt - what do you mean a typical blaze template? In my book that would be a bunch of HTML and curly brackets - but I don’t see how what you’ve provided fits in there… appreciate I’m obviously missing something!
Ok I’m following, I wasn’t really considering the helpers and actions as part of the template - but that of course makes sense.
However I’m still not sure how that code would apply… it’s likely more advanced than I am.
i.e. where is getReadmeFromGithub fitting in? Is that a helper? an action? The setup looks completely alien to me.
Maybe it;d help if I gave more context from my end - I’ve been trying to get a meteor call to actually give me something, and am getting nowhere, it’s always undefined (I’ve tried sync and async methods of using meteor call):
I tried sticking the call in data having seen a similar approach in an SO, but I’ve tried it pretty much everywhere, still always undefined and even if it wasn’t I’m not sure this is how I get it into the variable pool.
I had the same end result when trying to get the data into a helper (but this process is even less familiar to me, I’ve at least gotten data into templates via the router and publish/subscribe).
But like I said, you can also put this method.call into separate helper, as long (as you init this helper’s code in your HTML later by {{myHelper}}) or in a “click button” action.
Thanks for spotting that, did indeed get rid of the last error! (and yup, I have the ReactiveVar package!)
Running a log within the helper is still giving me undefined, however. Is that expected? i.e.
invoices: function () {
console.log(Template.instance().getInvoices.get());
return Template.instance().getInvoices.get();
}
undefined
(actually empty first, then undefined…)
I can’t get any output in the template still but I’m not sure if that’s because of how I’m trying to drill into the json - I’m guessing the helper should log it correctly, even if not immediately?
First - is your api get call actually returning any data. Can you check it in your meteor.method with console.log? It doesn’t even have to be in the callback, just do it after the http.call.
Second is the proper way of forcing the meteor.call callback to use the template’s data context. By default, callback creates a new, separate context, which makes it difficult to pass the data to our reactiveVar. In CoffeeScript it’s very easy to implement with the use of => but in JS it’s more tricky. The way I implemented it in the rewritten JS should work, but it wasn’t tested.
So i’d do another console.log right before getInvoices.set(result) and check it.
Perhaps use Template.instance().getInvoices.set(result) there too.
Somebody more fluent with JS would be handy here, as I’m a CS guy. Please, help!
You can write the JS like this, much easier to read
Template.BillingSettings.onCreated(function () {
this.getInvoices = new ReactiveVar();
var self = this;
Meteor.call('GetStripeInvoices', function (error, result) {
if (error) {
console.log(error);
throw new Meteor.Error(500, "Couldn't get invoices");
}
self.getInvoices.set(result);
});
});