Meteor reading data from a file stored on server - meteor

I want to show some data points on the client side, and I want to get the latitude, longitude and summary from a file stored on the server.
I have read a lot of posts saying to use papaParse using Meteor methods but I am not able to make it work.
Can you guys point me to right direction, my questions are:
In which folder to should I store a .txt, .csv or .json file in Meteor?
How to access it from the client and return the read data to client for display.

You can put your static files into private folder on the server and get them through Assets.
For exmaple, you have a data.json file in your private folder.
Method to get this data:
Meteor.methods({
getData() {
return JSON.parse(Assets.getText('data.json'));
}
});
You can now call this method on the client:
Meteor.call('getData', function(err, res) {
console.log(res);
});
UPD
Ok, how to display it.
Meteor.call runs async, so we will use reactivity to update our view on result.
Here is how we can display data on ourData template.
<template name="ourData">
<!-- Here you may want to use #each or whatever -->
<p>{{ourData}}</p>
</template>
Template.ourData.onCreated(function() {
this.ourData = new ReactiveVar();
Meteor.call('getData', (err, res) => {
if (err) {
console.error(err);
} else {
// Putting data in reactive var
this.ourData.set(res);
}
});
});
Template.ourData.helpers({
ourData: function() {
// Helper will automatically rerun on method res
return Template.instance().ourData.get();
}
});
reactive-var package required or you can also use Session.

Related

Ionic and SQLite wait until database info is loaded

I have a project on Ionic where I need to render some information of the database in the home page, something like a TODO program.
I already have some information on the database and I'm trying to render the list of items but I have the next problem:
First the home page is loaded without any result
Then the data from the database is loaded and printed on the screen
The problem is I want the view to wait until the database info is loaded until showing anything, I'm wondering if I can use some kind of loading icon.
I've followed the answer here: Open database before main controller is called in Ionic and SQlite
I have the database initialization working but as I've said, the data is loaded after the view is rendered.
I've tried using $ionicLoading but I didn't get any good result
This is my view:
.controller('homeCtrl', function ($scope, $state, $cordovaSQLite, DB) {
$scope.$on('$ionicView.enter', function() {
tasks = []
var query = "SELECT * FROM task;";
$cordovaSQLite.execute(DB.db, query, []).then(function(results) {
if(results.rows.length > 0) {
for (i=0; i<results.rows.length; i++){
console.log("SELECTED -> " + results.rows.item(0).title);
$scope.tasks.push(results.rows.item(i))
}
} else {
console.log("No results found");
}
}, function (err) {
$scope.tasks = [];
console.error(err);
});
$scope.tasks = tasks;
});
})
This is a video example of the issue I'm having right now:
https://youtu.be/H2fUYQuV3xg
Finally I found a solution following the advice of using resolve in my routes.
.state('home', {
url: '/',
templateUrl: 'templates/home.html',
controller: 'homeCtrl',
resolve: {
tasks: function(DB) {
return DB.getTasks();
});
}
}
})
I have a factory called DB where I have some functions to retrieve data from the database. On this example I load the tasks before entering on the URL using DB.getTasks()
To load the variable tasks resolved on the route I have to add the variable name on the function like this:
app.controller('homeCtrl', function (tasks) {
$scope.tasks = tasks;
})

Can Meteor preserve object references between server and client?

Is it possible to preserve pointers (object references) when you send data from the server to the client with Meteor? My initial tests say No, but perhaps there is another way to do this.
Here are server-side and client-side scripts:
Server.js
Meteor.methods({
test: function test() {
var object = {
key: ['value']
}
var output = {
object: object
, reference: object.key
}
console.log(output.reference[0])
output.object.key[0] = "changed"
console.log(output.reference[0])
return output
}
})
Server output:
// value
// changed
Client.js
Meteor.call("test", testCallback)
function testCallback(error, data) {
if (!error) {
console.log(data.reference)
data.object.key[0]= "edited"
console.log(data.reference)
}
}
Client output in the console:
// changed
// changed
No, this is not possible, although subscriptions do something similar. If your data is not in a collection, you can still publish it (see this.added and friends in the Meteor docs), and the data will show up in a collection in the client.

CollectionFS getting url of image file

Hi am using CollectionFS to upload and store images.
Uploading and storing the file is successful. I can retrieve file object from publication. But am unable to get URL for file. I need url for img tag
Following is how I declared collections.
Images = new FS.Collection("images", {
stores: [new FS.Store.GridFS("images")]
});
In browser console following code returns FS.File object
NewsImages.find().fetch()[0]
FS.File {createdByTransform: true, _id: "3kqLZRdLD33dKir2M", original: Object, chunkSize: 2097152, chunkCount: 0…}
But url is returning null.
NewsImages.find().fetch()[0].url()
null
Is there any extra work needed to generate URL?
More Details
I am using following allow rules.
NewsImages.allow({
//more others
download: function(){
if(Meteor.userId()){
return true;
}else{
return false;
}
}
});
I am getting following exception.
Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
I replaced Meteor.userId() with this.userId but this.userId is undefined.
Use a callback on saving the image and then put the image id into another
collection. Rough pseudo code...
Images.insert(yourFsFile, function (error, fileObj) {
if (error) {
// cry!
}
_.extend(yourItem, {imageId: fileObj._id});
Meteor.call('otherCollectioInsert', yourItem, function(error, result) {
if (error) {
// cry again!
}
// should have saved the image id so you can use the url
// http://www.you.com/cfs/files/images/the_id_you_saved
});
});
I hope this helps

Reading Files Asynchronously on Meteor

I am very new to Meteor so if my apologies if this is a dumb question:
How do you read a file from the filesystem on the server side, and get those contents displayed on the client side. Doing it synchonously isn't a problem because I can return it right away but as I understand from reading that defeats the purpose of Meteor so I am trying to do it asynchronously. However I dont know how to connect the client/server in this fashion. Publish/Subscribe seem to only be for db collections and not filesystem files. Any guidance you can give me would be very much appreciated.
if (Meteor.isClient) {
Template.body.helpers({
myfile: function(){
return file_contents;
}
});
}
if (Meteor.isServer) {
Meteor.methods({
myfile: function(){
var fs = Npm.require("fs");
fs.readFile('/opt/SI/SIAgent/conf/myfile','utf-8', function (err, data) {
file_contents = data;
});
}
});
}
You have to use Meteor.wrapAsync to turn Node.JS fs.readFile into synchronous-looking code so that you can return the result within the Meteor method.
var fs=Npm.require("fs");
fsReadFileSync=Meteor.wrapAsync(fs.readFile,fs);
Meteor.methods({
getMyFileContent:function(){
return fsReadFileSync("/opt/SI/SIAgent/conf/myfile","utf-8");
}
});

dynamically add files to the public folder and getting the refreshed results in meteor

I'm playing around with the idea of using Meteor as a backend for creating a static html generator (with an admin UI).
I want that, when triggered, a new file will be created on the public folder and instantly reviewed by the author on an iframe embed in the html.
The file gets created but two side effects happen:
The server is restarted.
The file is cached - so the user can't see that the change took place.
Any ideas?
if (Meteor.is_client) {
Template.hello.events = {
'click input' : function () {
Meteor.call('makeFile', 'filename.html', function(error, result){
alert(result);
});
//window.location = '/filename.txt';
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
};
}
if (Meteor.is_server) {
var fs = __meteor_bootstrap__.require('fs');
Meteor.startup(function () {
// code to run on server at startup
});
Meteor.methods({
'makeFile': function(fileName) {
/*
fs.unlink("public/"+fileName, function (err) {
if (err) throw err;
console.log('successfully deleted ');
});
*/
fs.writeFile("public/"+fileName, "<html><body><h1>test</h1></body></html>", function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved! "+ fileName);
}
});
return fileName;
}
});
}
I think the meteor server restarts whenever you change any file in a meteor subdirectory. So to prevent this don't write your files within the meteor app directory, make a created_files directory one level up or something. This is a good idea anyway, to separate the generated files from the code that's generating them.
Easiest way to show the content in the admin interface is probably to write it to the database (as opposed to trying to watch for directory changes). No sense re-inventing the wheel, since Meteor is designed to watch for db updates.
Create a collection (at the top, so it's on client & server):
GeneratedFiles = new Meteor.Collection("generated_files");
Then assign the file contents to a variable before writing them and in your fs.writeFile callback:
if(err) {
console.log(err);
} else {
GeneratedFiles.insert({name: fileName, contents: fileContents});
console.log("The file was saved! "+ fileName);
}
And then auto-publish the file contents to template in the client code (not sure why you want to use an iframe, seems like a div would work fine. But either way would probably work).
Hope that helps. And good luck, I think meteor is a great framework for this kind of thing. Most of the admin interfaces I use are still entirely synchronous and just annoying to work with.

Resources