publishing to user if he's logged in - meteor

I'm writing a meteor-angular2 project with the accounts-password package.
I'm trying to find out if the user is logged in and if he is, to publish the content.
this is my typescript code:
import {Meteor} from 'meteor/meteor';
import {RoomsCollection} from "../collections/rooms";
Meteor.publish('rooms',()=>{
if (!this.userId) {
return null;
} else {
return RoomsCollection.find();
}
});
as you can see i'm using this.userId but it seems that this is undefined.
this is the error:
TypeError: Cannot read property 'userId' of undefined
I don't quite understand how an anonymous function can have this.userId, i'm actually reading the book 'You First Meteor Application' from 2014. so maybe they where breaking changes... or i'm missing something.
I'm new to Meteor so any information regarding the issue would be greatly appreciated.

In your code you have:
()=>{
if (!this.userId) {
Don't use an arrow function if you want this to be driven by the caller! Instead do:
function() {
if (!this.userId) {
More
https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html

Related

How to Use Firebase with Nativescript-Vue?

I've been trying to implement just a simple Firebase fetch since November. At this point, I wish I'd just created a new Rails api; it would have been faster.
But everyone insists Firebase is Oh So Simple.
In app.js,
import firebase from 'nativescript-plugin-firebase';
That part seems OK.
Instructions are all over the place after that.
The plugin's ReadMe suggests an initialization:
firebase.init({
// Optionally pass in properties for database, authentication and cloud messaging,
// see their respective docs.
}).then(
function () {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
Several others have insisted that the init code is unnecessary. It does run without errors, but the code he gives after that produces nothing. Also,
const db = firebase.firestore;
const UserStatusCollection = db.collection("UserStatus");
UserStatusCollection.get();
produce an empty object {}.
Here's my Firebase collection:
If I wrap the firebase call in async/await (and no one is showing it as this complicated),
async function getFireStoreData() {
try {
let result = await this.UserStatusCollection.get();
console.log(result);
return result;
}
catch (error) {
console.error(
"UserStatusCollection.get()" + error
);
}
}
And call that
let temp2 = getFireStoreData();
console.log("temp2:" + temp2);
All I ever get is an object promise.
As I said, I wish I had just built up a new Rails API and had a far simpler life since November.
Your getFireStoreData method is asynchronous and you're not awaiting it. That is probably the reason why you're getting a promise back. Try to await getFireStoreData(). See if that works.
Since it's also a promise, you can try to use .then.
getFireStoreData().then(data => {
console.log(data);
})

Redirect page if no results from Firebase query

I am using VueJS and Firebase to return results for users, this works correctly
export default{
firebase() {
return{
cSites: db.ref('users/').orderByChild('url').equalTo(this.$route.params.uid)
}
}
}
I am trying to work out how to redirect the app to another page if no results are returned but cant seem work out how. If tried with the readyCallback() function, but together with the existing firebase function did not work.
Thanks in advance for any help.
I'm extrapolating from the docs and the source code, maybe this will work for you
firebase: function() {
return {
cSites: {
source: db.ref('users/').orderByChild('url').equalTo(this.$route.params.uid),
readyCallback: function () {
if (!this.cSites) {
this.$route.router.go('/'); // test and redirect here
}
}
}
}
}
Note when testing the 'function syntax', I get a warning in the console, but the result is ok.
[Vue warn]: Invalid value for option "firebase": expected an Object, but got Function.
Ref Github vuefire issue #133
It's a false alarm. You can use a function for the firebase property. The warning shouldn't appear.
For reference, vuefire.js
function bind (vm, key, source) {
var asObject = false
var cancelCallback = null
var readyCallback = null
// check { source, asArray, cancelCallback } syntax
if (isObject(source) && source.hasOwnProperty('source')) {
asObject = source.asObject
cancelCallback = source.cancelCallback
readyCallback = source.readyCallback
source = source.source
}
To elaborate, cSites is the source object, with properties source and readyCallback.
Using the function syntax allows a kind of 'late binding', so that 'this' has a value at the time the function is called.

Meteor: callLoginMethod not found error

I'm having difficulty invoking a login method, it follows
$ meteor list
Accounts-base 1.2.14 A user account system
Ecmascript 0.6.1 Compiler plugin that supports ES2015 + in all .js files
Meteor-base 1.0.4 Packages that every Meteor app needs
React 15.0.1 Everything you need to use React with Meteor.
Static-html 1.1.13 Defines static page content in .html files
/server/main.js
import { Accounts } from 'meteor/accounts-base'
Accounts.registerLoginHandler('simples', (ttt) => {
console.log(ttt);
});
/client/main.js
autenticar(){
Accounts.callLoginMethod({
methodName: 'simples',
methodArguments: [{ tipo : 'simples' }],
validateResult: function (result) {
console.log('result', result);
},
userCallback: function(error) {
if (error) {
console.log('error', error);
}
}
})
}
When calling authenticar(), I get this error:
errorClass
  Details: undefined
  Error: 404
  ErrorType: "Meteor.Error"
  Message: "Method 'simples' not found [404]"
  Reason: "Method 'simples' not found"
Where is the error?
I've never used this API personally, but from a quick glance through the Meteor internals, I see a couple issues.
Accounts.registerLoginHandler only adds an additional handler to an array of built-in handlers which are called as part of the default Meteor login process.
If you are trying to plug in an additional handler into the existing process, you should call Accounts.callLoginMethod without the methodName key.
Calling Accounts.callLoginMethod with methodName will bypass the built-in handlers completely and replace them with your custom method, however this method needs to be declared separately by you with Meteor.methods, not registerLoginHandler.
So, that's probably your error -- you need to define your simples method with Meteor.methods. Also, you should check the code for the requirements of this method, see the comments in the code here:
https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_client.js
Only to complement and keep as a referral for someone else to get here. That way it's working
client.js
Accounts.callLoginMethod({
methodArguments: [{tipo: 'simples'}],
validateResult: (result) => {
console.log('success', result);
},
userCallback: function(error) {
if (error) {
console.log('error', error);
}
}
});
server.js
Meteor.startup(function () {
var config = Accounts.loginServiceConfiguration.findOne({
service : 'simples'
});
if (!config) {
Accounts.loginServiceConfiguration.insert({ service: 'simples' });
}
});
Accounts.registerLoginHandler((opts) => {
if(opts.tipo === 'simples'){
return Accounts.updateOrCreateUserFromExternalService ('simples', {
id: 0 // need define something
}, {
options : 'optional'
})
}
});

ng2 display object in html

I'm trying to work out how to display an object in html using angular2. In ng1 I assigned to a variable and double braced the variable name in the html and bingo! Now I can't seem to get any data displayed at all.
Here is my simple method call:
onSubmit(value: oSearch): void {
console.log('you submitted value: ', value);
Meteor.call('methodName',value.type,value.year,value.idNumber, function(error,result) {
if (error) {
console.log('failed', error);
} else {
this.oResult = result[0];
console.log('successful call', this.oResult);
}
})
}
The object gets printed to the console. But I cannot get it to render by using:
{{oResult}}
oResult is declared using
oResult:Object;
Completely new to ts and ng2.
Update
Okay, I tried NgZone, but that didn't work. I'm getting behaviour I really don't understand.
} else {
console.log('successful call', result[0].topItem);
this.oResult = result[0];
console.log('successful call', this.oResult);
Both console.logs print the object correctly but oResult displays as [object Object]
If I change to:
this.oResult.topItem = result[0].topItem
then I get a Meteor error thrown and the 2nd console.log doesn't print. The error is:
Exception in delivering result of invoking 'methodName': TypeError: Cannot set property 'topItem' of undefined
My server method was working perfectly with ng1. I've tried a synchronous version of http but no change in behaviour has resulted.
Perhaps someone knows of a tutorial demo of http method call using updated angular2-meteor that I can fork?
Angular doesn't recognize the value change if fields are updated by code running outside Angulars zone. Inject zone: NgZone and run the code within zone.run(...). It might also be sufficient to initialize the library within Angular to make it use the async API patched by Angular which notifies Angular about possible changes.
constructor(private zone: NgZone) {
}
onSubmit(value: oSearch): void {
console.log('you submitted value: ', value);
Meteor.call('methodName',value.type,value.year,value.idNumber, function(error,result) {
if (error) {
console.log('failed', error);
} else {
zone.run(function() {
this.oResult = result[0];
console.log('successful call', this.oResult);
});
}
});
}
See also Service events do not affect template correctly for an example.

"Object is not a function" in a Meteor route

I just created two routes that work just fine, but I'm getting an odd error in the console that I would like to fix.
Exception in callback of async function: TypeError: object is not a function
at OnBeforeActions.loginRequired (http://localhost:3000/client/router/config.js?8cea1a53d7ab131377c2c4f91d534123cba79b70:12:20)
This error shows up every time I visit the same page.
This is my config.js file:
Router.configure({
layoutTemplate: "uMain"
});
var OnBeforeActions = {
loginRequired: function (pause) {
"use strict";
if (!Meteor.userId()) {
this.render("uLogin");
return pause();
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
except: ["uLogin"]
});
The idea is to redirected all user who are not logged in to "uLogin".
It works (or I haven't found any bugs so far).
What am I doing wrong?
You can see the line where you have the error in developers console when you click on link http://localhost:3000/client/router/config.js?8cea1a53d7ab131377c2c4f91d534123cba79b70:12:20 in your console.
Your problem is that new Iron Router does not use pause() anymore. Remove pause from your onBeforeAction.
Developers console is your good friend. Learn how to use it.

Resources