FirebasePaginator is not a constructor - javascript

I'm using a library developed by Chris Esplin (firebase-paginator) but i get FirebasePaginator is not a constructor when i try to use it. I'm actually developing a PWA in Vue.js 2.0, the script where this is getting called it's in app-name/src/store/index.js which is the main file for manage vuex states, mutations, actions and getters.
var FirebasePaginator = require('firebase-paginator')
var options = {
pageSize: 20,
finite: true,
auth: 'SomeAuthToken',
retainLastPage: false
}
var ref = firebase.database().ref('track')
var paginator = new FirebasePaginator(ref, options)
var collection = null
paginator.once('value')
.then(() => {
collection = paginator.collection
console.log(paginator, collection)
})
I've tried with a custom paginator that found googling, i adapted to eslint rules and i get the same constructor error when i make the call with new

I'm unfamiliar with Vue.js, but I only ever designed FirebasePaginator to work with script tags for the browser or require calls for Node.js. The "not a constructor" error indicates that the library wasn't imported correctly.
Try adding /node_modules/firebase-paginator/firebase-paginator.js to the page in a script tag. I'm sure there's a way to get require('firebase-paginator') to work with require statements in the browser, but I don't use them that way myself, so if you figure it out, I'd welcome a pull request.
Also, make sure that you don't use your legacy admin auth token in the browser. I think the REST API will work with auth tokens from your authenticated user, but I haven't played with that feature in a while, so I'm uncertain. Infinite pagination may be easier to implement.

Related

Angular Material table datasource is not syncing with my HTTP calls and not re rendering the dom

So I'll get straight to the point, im building an angular application and I am using Angular Material Tables. Bit of a disclaimer I'm pretty new to Angular and development
So basically I'm creating a dataSource variable to where I'm going to constantly update my tables data with each call and this is the code where that happens
const siteFilter: SiteFilter = {}; this.siteControllerService.getAllSitesFilteredAndSorted(siteFilter, this.page).subscribe((data) => { this.data = data; // eslint-disable-next-line #typescript-eslint/no-non-null-assertion this.data.sort((a, b) => (a.siteId! > b.siteId! ? 1 : -1)); this.dataSource = new MatTableDataSource(this.data); this.dataSource.sort = this.sort; });
(Originally the last 3 lines were also in ngoninit and I put them into a 1 second timeout which did solve my issue but it is extremely not good at all, I'm also aware that its bad practice to put this into my constructor but its there because I am in the belief that if it runs before my oninit and I get the data and then trigger a detechchanges on my oninit it should detect that my data is not up to date with the current dom and re render it.)
my #Component looks like this:
#Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-table', templateUrl: './table.component.html', styleUrls: ['./table.component.scss'], })
And inside the ngOnInit I am calling the this.ref.detectChanges(); which is in the constructor as this:
private ref: ChangeDetectorRef
Now the reason this is all here is that right now the above HTTP call returns me an array of objects I put that object into the dataSource and my table should re render with the newly added data as far as I'm aware, but it came to my attention that sometimes I make a call to get 20 entries of the data I want, and only 14 or 16 or however much is visible on my table and so I got confused logged the response and even though my table had 16 entries the object I got was precisely 20 as much as I asked for.
Not sure how this stackoverflow works but I'll continue on inside the what did I try section so I tried to use a changeDetector since I realsed that the data is there inside my variable but its not updatin the DOM I implemented the above example and I'm still on the same issue, as if the http response time is a big longer than usual then the data I see in my table is not what the dataSource is at that moment.
Which means basically that the dom is not representing the actual data inside my dataSource.
So my question is basically is there a way for me to detect whenever my http call a 100% ended and then I do the this.dataSource = new MatTable... etc. I've tried going into the success arrow function inside the call but that didin't do much either and I've also looked up how async await works but I got really nowhere there since im really newbie at this still and have no idea how to implement an async await functionality.
Not sure if this information is relevant at all but I'll share this since If it is then thank god we got this out of the way but none of the http calls are created by me or anyone else at that matter, this generated through the dto-s the BE has and whatnot which is is somehow compiled automatically into a service and downloaded as an NPM package from an artifactory and we use the Service which this package has and we cannot edit the http calls at all we just use the respective method and give the asked data to them. Not sure if this is relevant or a good to know for the question but here it is.
If I could get any direction to go to and help that would be great.
(I asked chat GPT also if someone suggest me that, offered me the above example which didn't work.)
Okay so after 2 weeks of struggling to understand why this would hapen I have finally been able to figure out a solution if anyone is ever interested or has a similar issue this is what solved it for me.
I've moved the logic to get the data from the API to its own method as shown here:
GetAllSites() {
const siteFilter: SiteFilter = {};
this.siteControllerService
.getAllSitesFilteredAndSorted(siteFilter, this.page)
.pipe(first())
.subscribe((data) => {
this.data = data;
this.data.sort((a, b) => (a.siteId! > b.siteId! ? 1 : -1));
this.dataSource = new MatTableDataSource(this.data);
this.dataSource.sort = this.sort;
this.ref.detectChanges();
});
And now this is the first thing what is called inside my ngOnInit hook.
The only difference is that im using a .pipe(first()) before my subscription, I have played around with this solution with different sizes of data and simulation of backend delay and this seems to be working, and whenever the call is finished the dataSource is updated correctly and the dom is refreshing with the newly updated data.
What a ride.

Using Redux with vanilla JS how can I reach it without passing it to every component?

I'm using Redux in a vanilla JS project. I have a bunch of small modular UI files and controllers and such. In those UI files I might have code like:
const ExampleForm = function (StoreInstance) {
return $('<form />', {
submit: () => {
StoreInstance.dispatch({
type: 'EXAMPLE_DISPATCH',
post: {
message: $TextareaComponent.val()
}
})
return false
}
})
}
The issue is I have a lot of simple view files like this and many of them are nested and I'm finding it to be ugly and error prone to have the store passed as a param to everything.
For example, I trimmed it for brevity but the form component has form element components such as a textarea. Currently I see two options of managing the Store:
Setting it to window when creating it in my entry file (index.js) and then just accessing Store globally. This seems the nicest, although not "best practice" and makes unit testing and server side rendering a bit harder.
Passing it to every component tediously. This is my example above. This I'd consider as "best practice" but it's pretty annoying to do for every file you make almost.
I'm wondering if there's any alternatives or tricks to passing the store instance. I'm leaning towards just making it global.
You could use the constructor pattern and create every view as new ConnectedView(). The ConnectedView would have a memoized instance of the store (this.store within the view), so it doesn't need to be global.

Using the .find().fetch() from within a function in Meteor

I am making a project with Meteor and I'm having some issues trying to get data out of mongodb in JavaScript. I have the following in a function:
console.log(Time.find({today: "Saturday"}).fetch());
In my publish.js file on the server side I have the following:
Meteor.publish("time", function () {
var currentUserId = this.userId;
return Time.find({user: currentUserId});
});
And In my subscriptions file I have the following:
Meteor.subscribe("time");
This function gets called later down in the code but it returns an empty array. If I run this code in my browsers console it returns an array with 2 objects in it, which is correct. This leads me wondering if I can use the .fetch() function from within my code? As if I leave off the .fetch() it returns what looks like the usual giant object. My real problem is I need the data in the form that .fetch() gives it to me in. I think it's because the function gets triggered before the data gets a chance to load in, as if I switch out the .fetch() for a .count() it returns 0.
Is there any way around this or a fix?
Where are you you running that console.log?
There are a couple fundementals here that I believe you may have glossed over.
1 Pub / Sub
This is how we get data from the server, when we subscribe to a publication i becomes active and begins to send data, this is neither instant or synchronous, (think of it more like turning on a hose pipe), so when you run your console.log, you may not yet have the data on the client.
2 Reactive contexts
One of the fundamental aspects to building anything in meteor is its reactivity. and it helps to start thinking in terms of reactive and non reactive contexts. A reactive context is one that re-runs each time the data it depends on changes. Using an autorun (Tracker.autorun or this.autorun insdie a template lifecycle callback) or a template helper are good examples. By placing it in a template helper it will re-run when the data is available.
Template.Whatever.helpers({
items: function() {
// ...do your find here.....
}
});
As items is a reactive context, depending on the collection data, it re-run when that changes, giving you access to the data when the client has them.
3 Retrieving Non Reactive Data
Alternatively it is also possible to retrieve data non-reactively by using Meteor.call with a meteor method, and then doing something with the result, in the callback to the Meteor.call. Depending on what you're doing, Meteor.wrapAsync may also be your friend here.
a simple example (out of my head, untested) :
// on the server
Meteor.methods({
gimmeStuff: function() {
return "here is your stuff kind sir!";
}
});
// on the client
Meteor.call('gimmeStuff', function(err, result) {
if (err || !result) {
console.log("there was an error or no result!");
return false;
}
console.log(result);
return result;
});
4 Its Unlikely that you actually need ithe .fetch()
If you're working with this in a template, you don't need a fetch.
If you want this to be non-reactive you don't need a fetch
As one of the commenters mentioned, a cursor is just a wrapper around that array, giving you convenient methods, and reactivity.
5 Go Back to the Begining
If you haven't already, I would highly recommend working through the tutorial on the meteor site carefully and thoroughly, as it covers all of the essentials you'll need to solve far more challenging problems than this, as well as, by way of example, teach you all of the fundamental mechanics to build great apps with Meteor.

How do I utilize actions and components to handle client side errors with Ember?

From what I've seen, most people use an external service that 'just works' and then they throw in some code in an initializer to report the errors.
In my initializer, so far I have:
Ember.onerror = function(error) {
displayError(error);
};
and displayError shows an error notification (similar to the Atom editor's error notifications)
But as I'm trying to add functionality to my displayError function (appending multiple errors, close one / all, showing stacktrace, eventually posting issues to github, etc), I've been finding that it's just VERY cumbersome to go back to vanilla javascript, and am wondering if there is a way to utilize ember to report errors that happen in my app.
Does anyone either:
- Know of an addon that does all this for me (I'm not interested in using a bug reporting service other than github)
- Know of a way to have Ember.onerror trigger an action in the application controller so I can have use components to render the errors, and have much easier development implementing what I need?
You can always try and use something like Ember.Instrumentation.
This will allow you fire off an event from inside the Ember.onerror callback that you can subscribe to anywhere else in your app. So let's say you create a component that lives at the root of your application. You can then subscribe that component to the error event and trigger when to display the error. Ember.instrument() also allows you to pass a payload which can be the error object itself.
In the root of your app you can have something like this:
Ember.onerror = function(error) {
Ember.Instrumentation.instrument("app.error", error);
};
Then in you're component you can subscribe to events in the init function like this:
init: function() {
Ember.Instrumentation.subscribe("app.error", {
before: function(name, timestamp, payload) {
// do logic here with error
},
after: function() {
// optional cleanup work here
}
}
}

Waiting for meteor collection to finish before next step

I have a Meteor template that should be displaying some data.
Template.svg_template.rendered = function () {
dataset_collection = Pushups.find({},{fields: { date:1, data:1 }}, {sort: {date: -1}}).fetch();
a = moment(dataset_collection[0].date, "YYYY/M/D");
//more code follows that is also dependent on the collection being completely loaded
};
Sometimes it works, sometimes I get this error:
Exception from Deps afterFlush function: TypeError: Cannot read property 'date' of undefined
I'm not using Deps in any context. As I understand it, the collection is being referenced before it is completely finished loading.
I therefore would like to figure out how to simply say "wait until the collection is found before moving on." Should be straightforward, but can't find an updated solution.
You are right, you should ensure that code depending on fetching the content of a client-side subscribed collection is executed AFTER the data is properly loaded.
You can achieve this using a new pattern introduced in Meteor 1.0.4 : https://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe
client/views/svg/svg.js
Template.outer.onCreated(function(){
// subscribe to the publication responsible for sending the Pushups
// documents down to the client
this.subscribe("pushupsPub");
});
client/views/svg/svg.html
<template name="outer">
{{#if Template.subscriptionsReady}}
{{> svgTemplate}}
{{else}}
Loading...
{{/if}}
</template>
In the Spacebars template declaration, we use an encapsulating outer template to handle the template level subscription pattern.
We subscribe to the publication in the onCreated lifecycle event, and we use the special reactive helper Template.subscriptionsReady to only render the svgTemplate once the subscription is ready (data is available in the browser).
At this point, we can safely query the Pushups collection in the svgTemplate onRendered lifecycle event because we made sure data made its way to the client :
Template.svgTemplate.onRendered(function(){
console.log(Pushups.find().fetch());
});
Alternatively, you could use the iron:router (https://github.com/iron-meteor/iron-router), which provides another design pattern to achieve this common Meteor related issue, moving subscription handling at the route level instead of template level.
Add the package to your project :
meteor add iron:router
lib/router.js
Router.route("/svg", {
name: "svg",
template: "svgTemplate",
waitOn: function(){
// waitOn makes sure that this publication is ready before rendering your template
return Meteor.subscribe("publication");
},
data: function(){
// this will be used as the current data context in your template
return Pushups.find(/*...*/);
}
});
Using this simple piece of code you'll get what you want plus a lot of added functionalities.
You can have a look at the Iron Router guide which explains in great details these features.
https://github.com/iron-meteor/iron-router/blob/devel/Guide.md
EDIT 18/3/2015 : reworked the answer because it contained outdated material and still received upvotes nonetheless.
This is one of those problems that I really wish the basic meteor documentation addressed directly. It's confusing because:
You did the correct thing according to the API.
You get errors for Deps which doesn't point you to the root issue.
So as you have already figured out, your data isn't ready when the template gets rendered. What's the easiest solution? Assume that the data may not be ready. The examples do a lot of this. From leaderboard.js:
Template.leaderboard.selected_name = function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
};
Only if player is actually found, will player.name be accessed. In coffeescript you can use soaks to accomplish the same thing.
saimeunt's suggestion of iron-router's waitOn is good for this particular use case, but be aware you are very likely to run into situations in your app where the data just doesn't exist in the database, or the property you want doesn't exist on the fetched object.
The unfortunate reality is that a bit of defensive programming is necessary in many of these cases.
Using iron-router to wait on the subscription works, but I like to keep subscriptions centrally managed in something like a collections.js file. Instead, I take advantage of Meteor's file load order to have subscriptions loaded before everything else.
Here's what my collections.js file might look like:
// ****************************** Collections **********************************
Groups = new Mongo.Collection("groups");
// ****************************** Methods **************************************
myGroups = function (userId) {
return Groups.find({"members":{$elemMatch:{"user_id":userId}}});
};
// ****************************** Subscriptions ********************************
if(Meteor.isClient){
Meteor.subscribe("groups");
}
// ****************************** Publications *********************************
if(Meteor.isServer){
Meteor.publish("groups", function () {
return myGroups(this.userId);
});
}
I then put collections.js into a lib/ folder so that it will get loaded prior to my typical client code. That way the subscription is centralized to a single collections.js file, and not as part of my routes. This example also centralizes my queries, so client code can use the same method to pull data:
var groups = myGroups(Meteor.userId());

Categories

Resources