Updating template after http call in Meteor - javascript

I'm making a new app with Meteor and I'm trying to get some public Github repos. I've written this call-method tuple:
Meteor.call('getRepositories', function(error, results) {
console.log(results);
});
Meteor.methods({
getRepositories: function(user) {
var response = Meteor.http
.call('GET','https://api.github.com/users/{username}/repos');
return response.data;
}
});
The problem is... how can I achieve to update the template with repositories names?
Thanks!

// your_tmpl template {{#each repos}}
{{name}}
{{/each}}
// js template manager
var reactiveRepos = new ReactiveVar([]);
Meteor.call('getRepositories', function(error, results) {
reactiveRepos.set(results); });
Template.your_tmpl.helpers({
repos: function() {
return reactiveRepos.get();
} });
// server.js
Meteor.methods({
getRepositories: function(user) {
var response = Meteor.http
.call('GET','https://api.github.com/users/{username}/repos');
return response.data;
}
});
You could use ReactiveVar (http://docs.meteor.com/#/full/reactivevar_pkg) package, that allow us to create reactive variables and use it in reactive environment, like helpers. Sure, you may want use it inside templates hooks as onRendered or onCreated for example, and bind it to your template.

Related

Kibana Customized Visualization with ES and Angular Doesn't Work

First, I try to make a custom visualization in Kibana with learning here.
Then, I want my custom visualization to display like the clock how many hits my elasticsearch index has dynamically .
So, I changed some codes in above tutorial but they don't work.
Chrome Devtools tells says Error: The elasticsearch npm module is not designed for use in the browser. Please use elasticsearch-browser
I know I had better use elasticsearch-browser perhaps.
However, I want to understand what is wrong or why.
public/myclock.js
define(function(require) {
require('plugins/<my-plugin>/mycss.css');
var module = require('ui/modules').get('<my-plugin>');
module.controller('MyController', function($scope, $timeout) {
var setTime = function() {
$scope.time = Date.now();
$timeout(setTime, 1000);
};
setTime();
var es = function(){
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'localhost:9200',
log: 'trace'
});
client.search({
index: 'myindex',
}).then(function (resp) {
$scope.tot = resp.hits.total;
}, function (err) {
console.trace(err.message);
});
};
es();
});
function MyProvider(Private) {
...
}
require('ui/registry/vis_types').register(MyProvider);
return MyProvider;
});
public/clock.html
<div class="clockVis" ng-controller="MyController">
{{ time | date:vis.params.format }}
{{tot}}
</div>
Thank you for reading.
Looks like the controller in angularjs treats the elasticsearch javascript client as if it was accessing from the browser.
To elude this, one choice will be by building Server API in index.js and then make kibana access to elasticsearch by executing http request.
Example
index.js
// Server API (init func) will call search api of javascript
export default function (kibana) {
return new kibana.Plugin({
require: ['elasticsearch'],
uiExports: {
visTypes: ['plugins/sample/plugin']
},
init( server, options ) {
// API for executing search query to elasticsearch
server.route({
path: '/api/es/search/{index}/{body}',
method: 'GET',
handler(req, reply) {
// Below is the handler which talks to elasticsearch
server.plugins.elasticsearch.callWithRequest(req, 'search', {
index: req.params.index,
body: req.params.body
}).then(function (error, response) {
reply(response);
});
}
});
}
});
}
controller.js
In the controller, you will need to call GET request for above example.
$http.get( url ).then(function(response) {
$scope.data = response.data;
}, function (response){
$scope.err = "request failed";
});
In my case, I used url instead of absolute or relative path since path of dashboard app was deep.
http://[serverip]:5601/iza/app/kibana#/dashboard/[Dashboard Name]
*
Your here
http://[serverip]:5601/iza/[api path]
*
api path will start here
I used this reference as an example.

Meteor js | Display Json in view via helper

Im struggling with an issue using Meteor JS.
I call an api wich return me a Json array wich look like the one returned on this url (I don't put the whole array here cause of the size): https://blockchain.info/address/12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?format=json&offset=0
I call it server side like :
if (Meteor.isServer) {
Meteor.methods({
getWalletPreviousTx: function() {
var url = "https://blockchain.info/address/12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX?format=json&offset=0";
var result = Meteor.http.get(url);
if(result.statusCode==200) {
var tx = JSON.parse(result.content);
return tx;
} else {
console.log("Response issue: ", result.statusCode);
var errorJson = JSON.parse(result.content);
throwError("Couldn't fetch wallet balance from Blockchain, try again later !");
}
}
});
}
And i retrieve it to my view via an helper in a specific template :
Template.wallet.helpers({
addrTxs: function () {
Meteor.call('getWalletPreviousTx', function(err, tx) {
console.log(tx);
return [tx];
});
}
});
The console.log in the helper actually log my Json array wich mean it have access to it.
Now the part im struggling with is to retrieve this Json to my view, i've tried a lot of way and none of them works, actually i have this in my view :
<template name="wallet">
<table>
{{#each addrTxs}}
<ul>
{{> addrTx}}
</ul>
{{/each }}
</table>
</template>
The part of the Json I want to display is the "addr" and "value" of each transactions :
"inputs":[
{
"sequence":4294967295,
"prev_out":{
"spent":true,
"tx_index":97744124,
"type":0,
"addr":"1AWAsn8rhT555RmbMDXXqzrCscPJ5is5ja",
"value":50000,
"n":0,
"script":"76a914683d704735fd591ba9f9aebef27c6ef00cbd857188ac"
}
}
]
Fact is, i never managed to display anything from this Json array in my view, even puting directly this in my view doesn't show anything :
{{addrTxs}}
What am I doing wrong ? Can anyone help with this ?
Thanks for reading.
----------------------- Edit ---------------------
I think the problem is more that my helper and template are loaded before the api call is finished (because the console.log appear in my console like 3seconds after my page is rendered). How can i make my helper wait until the api call is finished before rendering it in the view ? I use iron router.
I have tried to add a waitOn action on my route in order to wait until my api call is finished :
Router.route('/wallet', {
name: 'wallet',
template: 'wallet',
loadingTemplate: 'loading',
waitOn: function () {
Meteor.call('getWalletPreviousTx', function(error, result) {
if(!error) {
Ready.set(result)
}
});
return [
function () { return Ready.get(); }
];
},
action: function () {
if (this.ready())
this.render();
else
this.render('loading');
}
});
The above code with the waitOn action seems to work (i have no errors) but i don't know the way to display in my view the specific result from :
if(!error) {
Ready.set(result)
}
Transactions are contained in tx.txs, iterates through that.
Template.wallet.helpers({
addrTxs: function () {
Meteor.call('getWalletPreviousTx', function(err, tx) {
console.log(tx);
return tx.txs;
});
}
});
You're right, you need to use the sessions variables with async call.
First, call method on created :
Template.wallet.created = function () {
Meteor.call('getWalletPreviousTx', function(err, tx) {
console.log(tx.txs);
Session.set('tx', tx.txs);
});
};
Helper should look like this :
Template.wallet.helpers({
addrTxs: function () {
return Session.get('tx');
}
});

Grab attribute of current record for Meteor Method Call

I am working on a project to pull in twitter timeline's for selected teams/players. When I am on the team/_id page, how can I grab an attribute to path through a method?
Below is my client side javascript, as well as the relevant route from iron router. When I type in something like "patriots" to the "????" section, I get a result. I would like to do this dynamically, I currently have the twitter handles stored under the twitter attribute.
Template.tweets.helpers({
teams: function() {
return Teams.find();
},
});
Template.tweets.onRendered(function () {
var twitterHandle = "???";
Meteor.call('getTimeline', twitterHandle, function(err,results){
if (err) {
console.log("error", error);
};
console.log(results);
Session.set("twitter", JSON.parse(results.content));
})
return Session.get("twitter");
});
Router.route('/teams/:_id', {
name: 'teamView',
template: 'teamView',
data: function(){
var currentTeam = this.params._id;
return Teams.findOne({ _id: currentTeam });
var twitterHandle = this.params.twitter;
return Teams.findOne({twitter: twitterHandle});
}
});
<template name="tweets">
<h3>Tweets</h3>
<div class="container">
{{twitter}}
</div>
</template>
You should be able to access all information from the current route using the Router.current() object. In your case you can use Router.current().params._id to get the _id param:
var twitterHandle = Router.current().params._id;
Edits based on your comments below
I did not notice that you were calling the Teams.findOne function twice in your route's data function. Form the looks of it you're already storing the twitter handle in the Teams collection, so you merely need to access the data that's returned by the route.
Template.tweets.helpers({
twitterData: function() {
//return the data stored in the callback function of the Meteor method call in the onRendered event
return Session.get('twitter');
}
});
Template.tweets.onRendered(function () {
//clear any previously stored data making the call
Session.set('twitter', null);
//property of the team document returned by the data function in the route.
var twitterHandle = this.data.twitter;
Meteor.call('getTimeline', twitterHandle, function(err,results){
if (err) {
console.log("error", error);
} else {
Session.set("twitter", JSON.parse(results.content));
}
});
});
Router.route('/teams/:_id', {
name: 'teamView',
template: 'teamView',
data: function(){
var currentTeam = this.params._id;
return Teams.findOne({ _id: currentTeam });
}
});
<template name="tweets">
<h3>Tweets</h3>
<div class="container">
<!-- twitterData will be an object, so you'll need to figure out what properties to display and use dot notation//-->
{{twitterData}}
</div>
</template>

How should I store current user details in EmberJS?

I have an EmberJS application generated using ember-cli. I'm currently using simple-auth with a custom authenticator.
In the authenticator, when the user logs in I want to save his details so that I can use it later.
I have the following code:
authenticate: function(options) {
var self = this;
return new Ember.RSVP.Promise(function(resolve, reject){
API.user.login(options.username, options.password, true).done(function(data) {
// #TODO: Save current user
resolve(data.id);
}).fail(function() {
reject();
});
});
},
User data is available in the variable data.user.
I tried using Ember.set('App.currentUser', data.user); but it's not working. What should I do?
I think it works easiest to use an initializer. Theres several ways you can resolve the user, I think it is easiest if you pass the user_email alongside the grant token from the API
//initializers/session-user.js
import Ember from "ember";
import Session from "simple-auth/session";
export function initialize(container) {
Session.reopen({
setCurrentUser: function() {
var accessToken = this.get('access_token');
var self = this;
if (!Ember.isEmpty(accessToken)) {
return container.lookup('store:main').find('user', {
email: self.get('user_email')
}).then(function (users){
self.set('currentUser', users.get('firstObject'));
});
}
}.observes('access_token')
});
}
export default {
name: 'session-user',
before: 'simple-auth',
initialize: initialize
};
Check this thread for where the idea of this came from: http://discuss.emberjs.com/t/best-practice-for-loading-and-persisting-current-user-in-an-authenticated-system/6987
And if you are using simple-auth > 0.8.0-beta.1 you will need to adjust the initializer
I ended up creating a custom Sessions controller and setting the current user object there, and then creating an alias from the application controller.
Something like what's in this article.

live update view in ember

I build application using web-socket and I want dynamically change view
I have code in my model:
model: function () {
var store = this.store;
var socket = new_socket();
socket.on('message', function (message) {
store.push('record',message);
});
return store.find('consultation');
}
And data successfully loading into ember store, but ember doesn't update view.
What I need to do?
For example when I use save all works fine:
var record = this.store.createRecord('record',{});
record.save()
UPDATE:
I found this solution:, but it's also not working
My controller (consultation.js):
export default Ember.ObjectController.extend({
needs: ['application'],
records: function() {
console.log(this.get('store'));
return this.get('store').filter('record', function(record) {
console.log(record);
});
}.property('records'),
Template:
{{#each item in controller.records}}
{{/each}}
Model consultation looks like this (with hasMany field):
export default DS.Model.extend({
records: DS.hasMany('record', { async: true }),
});
Second console.log is not printing,
I solved it like this
var obj = store.push('record', jsonObj.message);
this.controllerFor('consultation').get('records').pushObject(obj);
But it's looks like not good. In which way I can make auto synchronization between model and controller
You have computed properties that are dependent on themselves in your controller. Also, you really should not be pushing anything to the store, conceptually, when you receive something on your socket, your model changed, you want to capture that notion in your code, so you really should be updating the model when you get a socket message. The way I would do this would be to do something like the following:
in the router,
model: function() {
var records = this.store.find('consultation',{});
var socket = new_socket();
socket.on('message', function (message) {
records.pushObject(message);
});
return records;
}
The controller does not need to have any computed properties at all.
and in the template, the code would just be:
{{#each content}}
//do something here
{{/each}}
I'm a little confused about your use of consultation and record in the code.

Categories

Resources