$firebase promise resolve in phonegap app - firebase

i am stuck with this for few days now.
I have route with resolve, which looks something like this:
.when('/list/',{
controller : 'list',
templateUrl : 'template/list.stache',
resolve : {
list : function($q,$firebase){
var d = $q.defer(),
ref = new Firebase(_config.url+'/list/');
ref.once('value', function(s){
if(s.val() == null){
d.reject('Object not found');
}
d.resolve($firebase(ref));
});
return d.promise;
}
}
})
It works great in any browser, for some reason it fails in Android app ( using phonegap ), it loads data correctly, but when you try to save it ( using $save() ), data updates locally but fails to do so remotely.
Tested few theories, tried to call $firebase within controller, using something like:
$scope.fb = $firebase(new Firebase(_config.url+'/list/'))
$scope.fb.$on('loaded', function(d){
$scope.fb[$scope.fb.$getIndex()[0]].test = 'AAAAAA!'
$scope.fb.$save()
})
The above worked as should, so i assume it has something to do with promises.
Would anyone have any ideas?
EDIT ---
Still struggling to figure out the issue, but was able to narrow it down to resolve:
.when('/list/',{
controller : function(){
new Firebase('https://XXX.firebaseio.com/test/').push('Hey!');
},
templateUrl : 'template/list.stache',
resolve : {
list : function($q,$firebase){
var d = $q.defer(),
ref = new Firebase(_config.url+'/list/');
ref.once('value', function(s){
if(s.val() == null){
d.reject('Object not found');
}
d.resolve($firebase(ref));
});
return d.promise;
}
}
})
It fails. But :
.when('/list/',{
controller : function(){
new Firebase('https://XXX.firebaseio.com/test/').push('Hey!');
},
templateUrl : 'template/list.stache'
})
Works as expected.
Note that both approaches works fine in a browser ( tested on firefox and chrome ). It only fails when compiled to android app using phonegap.
Any ideas are appreciated.

I had the same thing. The connection is lost.
Use the function Firebase.goOffline(); and Firebase.goOnline();. This allows you to manually control the client connection.
Example:
var usersRef = new Firebase('https://samplechat.firebaseio-demo.com/users');
Firebase.goOffline(); // All Firebase instances are disconnected
Firebase.goOnline(); // All Firebase instances automatically reconnect
Link for reference

Related

MVC minification seems to creating duplicate variable names

This question seems to be more or less a duplicate of this one, but that one received no answers and is over 2 years old so I don't know what the protocol is (I tried to find out).
Anyway, I've written an ASP.NET MVC5 web app and it all works fine in debug. After publishing to the server with the Release configuration I started seeing the error "Uncaught ReferenceError: Cannot access 'n' before initialization".
After many hours of trawling through the code I think I've isolated the issue. I have this small function (it's a Knockout view model, but that's irrelevant):
eventIndexViewModel = function (params) {
let self = this;
// Map values from params object to properties of self
for (const [key, value] of Object.entries(params)) {
self['_' + key] = value;
}
self.eventsView = ko.observable(self._eventsView);
self.calendarToggleButtonClass = ko.pureComputed(function () {
return self.eventsView() === "calendar" ? "active" : "";
});
self.tableToggleButtonClass = ko.pureComputed(function () {
return self.eventsView() === "table" ? "active" : "";
});
};
After being minified and published to the server, if I view the source in the dev tools console it looks like this:
eventIndexViewModel = function(n) {
let t = this;
for (const [n,i] of Object.entries(n))
t["_" + n] = i;
t.eventsView = ko.observable(t._eventsView);
t.calendarToggleButtonClass = ko.pureComputed(function() {
return t.eventsView() === "calendar" ? "active" : ""
});
t.tableToggleButtonClass = ko.pureComputed(function() {
return t.eventsView() === "table" ? "active" : ""
})
}
It is overkill to map the properties for the params object in this way in this particular instance, but I have much larger view models with many more properties in the same project and I want to keep them code consistent, so go with it.
Unless I'm misunderstanding something, the minified version has renamed both the params variable and the key variable in the for statement to n, and I think that is what is causing my error. Certainly, that line with the for statement is where the error is thrown.
Am I understanding the cause of this problem correctly? If so, is it a bug in the minification process? And either way, how can I get around it?

Firebase reCAPTCHA has already been rendered in this element

Authenticate with Firebase with a Phone Number (JS) requires a mandatory reCAPTCHA verifier, it takes the ID of the container. For the ID of the container, I am generating a random one -
firebase_recaptcha_container: "recaptcha-container",
firebase_recaptcha_reset: function() {
if (typeof appVerifier != "undefined") {
appVerifier.reset()
appVerifier.clear()
}
let id = loadJS.firebase_recaptcha_container
let newID = loadJS.randomString(10)
$("#"+id).contents().remove()
$("#"+id).prop("id", newID)
loadJS.firebase_recaptcha_container = newID
return newID
}
then requesting for the RecaptchaVerifier and upon receiving I set this as a global variable window.appVerifier .
firebase_recaptcha: function(name_r="default") {
let promiseD = new firebase.auth.RecaptchaVerifier(name_r, {
'size': 'invisible',
'callback': function(response) {
resolve(response)
},
'expired-callback': function(r) {
console.log("expired", r)
},
'isolated' : false
});
return promiseD
},
_____________________
let container_recaptcha = $utils.firebase_recaptcha_reset()
window.appVerifier = await $utils.firebase_recaptcha(container_recaptcha)
It works totally fine for the very first time. But its a honest mistake for users not to use correct phone number. So for next time, I am doing the same thing again and getting error while generating the RecaptchaVerifier -
reCAPTCHA has already been rendered in this element
Which sadly does not make sense as the new element is totally different and also clear, reset methods were called following the documentation. I am neither using any other reCaptcha on this page. Refreshing the page might be a possible solution but that I really hate. Any insight would be helpful.
Thanks!
Finally found the solution, looks like it was a stupid mistake!
Invoking firebase.auth.RecaptchaVerifier adds new recaptcha scripts, every time! Hence all needed to be done is, calling it once, it does the rest on its own.
This won't get fixed just by implementing recaptchaVerifier.clear() method.
In the callback where you are passing this appVerifier, you'll have to implement the above clear method and add that "recaptcha-container" using ref
The below would be the element in render method:
<div ref={recaptchaWrapperRef}>
<div id="recaptcha-container"></div>
</div>
GenerateCaptcha function:
const generateRecaptcha = () => {
appVerifier = new RecaptchaVerifier(
"recaptcha-container",
{
size: "invisible",
},
authentication
);
Inside submit Callback:
if (appVerifier && recaptchaWrapperRef.current) {
appVerifier.clear();
recaptchaWrapperRef.current.innerHTML = `<div id="recaptcha-container"></div>`;
}
// Initialize new reCaptcha verifier
generateRecaptcha();

Meteor publish/subscribe not working

I'm working in meteor 1.7, and my publish/subscribe is returning only empty arrays.
file structure:
-all/
-shared.js
-client/
-main.js
-imports/
-Elsewhere.js
-server/
-main.js
shared.js:
Chats = new Mongo.Collection('chats')
client/main.js:
Template.main.onCreated(()=>{
Meteor.subscribe('chats')
});
server/main.js
Meteor.publish('chats', function(){
console.log(Chats.find().fetch()) //Shows that I have documents in the collection
return Chats.find();
});
Elsewhere.js
Template.Elsewhere.helpers({
chats(){
console.log(Chats.find().fetch()) //[]
return Chats.find().fetch()
}
})
Why don't I get what I'm publishing?
-------------------------------------New stuff-----------------------------------
I'm now unsure if it's a load order issue, reactivity issue, pub/sub issue, or a mix of them. I have this snippet
search(collection, where, id, part, callback){
var result
if(id){
console.log(Meteor.users.find().fetch()) //[]
result = Collections[collection].findOne(id)
}else{
result = Collections[collection].find(where ? where : {}, {many:true}).fetch()
}
if(result){
if(callback){
callback(result)
return
}else{
if(part){
return result[part]
}else{
return result
}
}
}
}
I'm also noticing that the output from this log is happening BEFORE my subscriptions. This file is located in /imports/scripts/tools.js
Inside an autorun block subscribe to 'chats' and check if handler is ready. Then find and fetch.
this.autorun(() => {
let handler = Meteor.subscribe('chats');
if(handler.ready()) {
console.log(Chats.find().fetch())
}
});
I realized that I was not using a reactive data source for my helpers, I was setting a Session variable when I called the tool.search function, which only ran once.

Meteor Spiderable, errors

when i test ?_escaped_fragment_= , i get
TypeError: 'undefined' is not a function (evaluating 'document.querySelectorAll.bind(document)')
http://localhost:3000/packages/material-design.js?e252ae03c7066a6ce33a348a22662a73cee8811e:75
http://localhost:3000/packages/material-design.js?e252ae03c7066a6ce33a348a22662a73cee8811e:315
http://localhost:3000/packages/material-design.js?e252ae03c7066a6ce33a348a22662a73cee8811e:318
http://localhost:3000/packages/material-design.js?e252ae03c7066a6ce33a348a22662a73cee8811e:778
The html in the body does show up but I do not get any meta tags and there is a huge blank space in the head before the title.
i followed http://www.meteorpedia.com/read/spiderable/ and ran phantomjs phantomtest.js
❯ phantomjs phantomtest.js [17:50:01]
Loading page...
Page load status: success
not ready, Meteor undefined
i got this.
Any idea what's wrong? Thanks.
In phantomjs, which is used by spiderable, the bind method is not supported. If you're the owner of material-design I would suggest replacing bind with _.bind. Otherwise, you can add a polyfill to your project to make sure that Function.prototype.bind is properly defined.
EDIT
To make sure your browser supports bind put this code somewhere in your code base:
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
The above implementation is copy/pasted from here.

Error: Cannot apply $push modifier to non-array in Meteorjs

This is a function to add a dictionary as a subitem of a main document.
addSubItem = function(id, data) {
s = Item.findOne(id);
if(s){
Item.update({_id:id},{$push:{'subItemsList':data}});
}
};
I verify the data passed and are a valid main document id a subitem data.
data = {num:1, value: 'Subitem1'};
This works fine yesterday with the latest version of meteor (0.4.2), but today I get this message at javascript console:
Error: Cannot apply $push modifier to non-array
I created and setup a new project and I still get the same.
Thanks to Lloyd, Nice workaround and thanks for the javascript crash course (i'm a begginer on it), but I found the solution: (note the "$push")
addSubItem = function(id, data) {
s = Item.findOne(id);
if(s){
Item.update({_id:id},{"$push":{'subItemsList':data}});
}
};
try this:
addSubItem = function(id, data) {
s = Item.findOne(id);
if(s){
s.subItemsList = s.subItemsList || [];
s.subItemsList.push(data);
Item.update(id, s);
}
};

Resources