ReactJS Meteor Pagination - meteor

I am creating application in Meteor using ReactJS for the UI. I ran into a problem. I am trying to read from a meteor collection and populate a grid with some data, this I have managed to achieve, but what I can't seem to figure out is how to do infinite scroll/pagination.
I stumbled across the paginate-subscriptions meteor package, but I can't seem to get it to work properly.
Here is my code:
Container = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
var handle = Meteor.subscribeWithPagination('my-coll', 10);
return {
items: MyCollection.find({}).fetch()
},
render() {
return (
<div>
{this.data.items.map(item => {
<p>{item}</p>
}}
</div>
)
}
})
Instead of rendering 10 items, it will render all the items in the collection, which is not what I want.
Help appreciated.

check Kurounin subscribe based pagination package. It works properly and no issues. Data tables also used. Check this link

You can use the Griddle Component for Grid it's good and provide all the functionality like Search sorting filter etc.
Griddle

Related

Show Loading Screen Until Data Is Populated - React & Meteor

I'm trying to populate a table and only want to show the data when everything has been fetched. I'd like to show a basic "Loading..." text. Currently I have this:
getNames() {
return Names.find().fetch();
}
render() {
let mapData = this.getNames().map((name) => {
return <Name key={name.id} name={name} />
});
if (!mapData) {
return (<h1>Loading...</h1>);
}
return (
<ul>
{mapData}
</ul>
);
}
This is just a basic example, but I'm grabbing alot of data from Names.find().fetch()... though it seems that once mapData starts getting populated, the data will partially load (showing possibly the first few items, then completing).
I know I'm not doing this correctly. I'm just wondering how other people deal with properly showing a progress bar in React.
I thought about just setting a delay in componentDidMount, but that doesn't seem to be a great solution.
Any help would be greatly appreciated!
Thanks!
T
Meteor.subscribe takes a callback that will be called once the subscription has loaded its data.
See: http://docs.meteor.com/#/full/meteor_subscribe

Reacting to changes made outside of Angular2

I've got a non-angular page made with fairly basic JS, and thought it'd be a splendid idea to try and add learn some Angular2 and use it for some new functionality.
My plan was that I'd bind an Angular2 component to an object that is being updated by the old code, and I'd use Angular2 magic to update a chunk of UI.
The problem is I cant convince Angular2 to react to any changes made in the outside JS. What the trick to doing that? Attempts at googling the problem lead to in depth explanations of Angular2's change detection process, which hasn't been helpful so far. Is this just an awful idea?
I found a random Angular2 jsfiddle and hacked it up to show the problem. Strings are added to 'window.names', but you dont see them until one is added from the angular side: https://jsfiddle.net/byfo3jg3/ . The code follows:
var names = ['Joe'];
setTimeout(function() {
names.push("Frank");
}, 1000);
setTimeout(function() {
names.push("Sterve");
}, 2000);
setTimeout(function() {
names.push("Garfield");
}, 3000);
(function() {
var HelloApp,
ListThing;
ListThing = ng
.Component({
selector: 'list-thing',
template: '<ul><li *ng-for="#name of names">{{name}}</li></ul>',
directives: [ng.NgFor]
})
.Class({
constructor: function() {
this.names = window.names;
setTimeout(function() {
this.names.push("Oh hai");
}.bind(this), 10000);
}
});
HelloApp = ng
.Component({
selector: 'hello-app',
template: '<list-thing></list-thing>',
directives: [ListThing]
})
.Class({
constructor: function() {}
});
document.addEventListener('DOMContentLoaded', function() {
ng.bootstrap(HelloApp);
});
}());
You will need to set the NgZone to window object and then call run function of the zone.
Please refer to Angular 2 How to get Angular to detect changes made outside Angular? SO Question
names should be component property to work inside of template:
constructor(){this.names = window.names}
Changes to window.names will not be detected by angular, so you have few options: poll names using setInterval(()=>{this.names = window.names}, 1000) or expose global callback:
constructor(zone:NgZone)
{
window.notify = ()=> {
zone.run(()=> {
this.names = window.names;
});
}
}
and call it from plain js window.notify() or use other methods to invoke change detection.
Is this just an awful idea?
Yes.
Angular's automatic change detection system assumes that changes to data (that you want your components to display) are happening inside an event handler that is monkey-patched by Zone.js. Because then Angular's change detection will execute when such an event handler fires (well, technically, it will execute after the event handler finishes).
If you want a component view to automatically update, you have to change the bound data inside Angular – inside the Angular zone. As #Jigar answered, you can modify your code to call angularZone.run(_ => // make changes here), but if you have to do that, you might as well move the code that manages and manipulates the data into a service (or a component, if the logic is minimal).
See also Günter's alternative approach: set up an event listener inside Angular (hence inside the Angular zone). Then fire that event whenever you make changes outside the Angular zone.

Initializing react component from asp.net

Hopefully this is a slam-dunk for someone out there...my essential problem is this: I've built up a very nice set of react components which i can render in my asp.net 4.5 mvc 6 application using react.js, flux, gulp, and browserify.
as long as i have it structured so that the react components have all the data they need everything is perfect. My issue now is that I would like to have an MVC view include the react stuff, and inject run-time properties into the top-level component as it is created. Since I'm brpowserify-ing all of my react code into a bundle, i just include the one script tag in my view:
<script src="/js/modules/AuthContainer.jsx"></script>
But whereas I would normally use JSX syntax to instantiate my component with props like this:
...the view in ASP.NET never gets translated to pure JS, so that fails.
I've also tried:
ReactDOM.render
(
React.createElement(AuthContainer, { successPath: '/home' }),
document.getElementById('reactRoot')
);
...from inside a script block in my view but i get:
Uncaught ReferenceError: AuthContainer is not defined
But i'm sure i'm exposing 'AuthContainer' via the browserify-ed bundle, so i don't understand why it's unable to resolve that component.
I know there's a React.NET way to do this, but i can't get that server-side rendering to work with my components because I'm using jQuery to fetch data in componentDidMount and the server-side rendering is choking looking for $() jQuery stuff.
I'd love to get the server side rendering going but right now i just need it to do work, one way of the other. Can someone provide a simple code snippet or gist of how to instantiate a React component from inside a cshtml file with run-time props?
One easy solution is this, just put your server side properties with Javascript in a global:
index.cshtml
<script>
var __config__ = {
base: "#MyBackEdnVariable",
initialCount: "#Count",
user: {
id: #user.id,
name: #user.name,
}
};
</script>
<script src="/js/modules/AuthContainer.jsx"></script>
And with React use that global variable:
AuthContainer.js
class AuthContainer extends React.Component {
render() {
return (
<div>{this.props.user.name}</div>
);
}
}
AuthContainer.defaultProps = {
initialCount: __config__.initialCount,
user: __config__.user
};
For posterity:
ReactDOM.render
(
React.createElement
(
MyComponent,
{
prop1: #numericValue,
prop2: '#textValue',
}
),
document.getElementById('reactRoot')
);
the magic was the jsx-alternative syntax, which i was aware of couldn't get a handle on that day. This allows you to instantiate react using pure JS and therefor just embed inside a simple script tag in your cshtml.
hth.

Adding components to existing Ractive instance

I have a somewhat weird question.
In Ractive we can do something like this.
App’s template:
<h1>My app</h1><SubComponent/>
And generally have SubComponent’s template access data from App.
Is there any way to have the same behaviour without mentioning SubComponent in the template?
Something like:
const App = new Ractive({el: ‘#myapp’, …………});
const SubComponent = Ractive.extend({ append: true, ………… });
const example = new SubComponent()
example.render(App.el)
But, with example’s template being able to access App’s data, maybe also giving App the chance to find it by using App.findComponent().
What I’m trying to do, is having unpredictable (= I can’t include them inside templates by default) nested components.
Hopefully this makes sense.
Any idea on how to do it?
I don't know if this will work out for you..
But you can just put a div with a known ID in
<h1>My app</h1><div id="subcomp" />
Then mount your dynamic SubComponent under there.
You can use can event like oncomplete - which will guarentee than div#subcomp has been added to dom.
oncomplete: function() {
this.mycompRef = new SubComponent( { el: '#subcomp' });
// You can skip findComponent and use mycompRef
}

Meteor, Form validation and Bootstrap accordion

I have a form in a Meteor application that contains a list of radio buttons that is made accessible by a Bootstrap accordion. I have implemented a validation routing in meteor that inserts classes into the input elements to mark them as valid/invalid.
Problem is: Everytime a validation state of one input element changes, the template is redrawn and the currently open accordion closes.
I solved this by doing this clumsy approach:
Meteor.startup(function() {
// track collapse state of accordion....
$('.collapse').on('shown', function() {
Session.set(addBookingCollapse, $(this).attr('id'));
});
});
Template.addrecord.helpers({
openAccordion: function(accordion) {
if (Session.get(addBookingCollapse) == accordion) {
return 'in'
};
}
});
<div id="collapseOne" class="accordion-body
collapse {{openAccordion 'collapseOne'}}">
...and so on for the other four collapsible elements
But for whoever's sake, there must be a more elegant solution? I do not want to waste a session variable for this....
It may help to put the input elements in {{#isolate}}{{\isolate}} blocks to avoid re-rendering the entire template. See: Meteor Isolates
I haven't really looked super close at your code/problem, but why do you use id's to target each of them on their own? Why not use a class for all of them like this:
$('.a-class-that-you-name').on('shown', function() {
var thisSpecificId = $(this).attr('id');
Session.set('addBookingCollapse', thisSpecificId);
});
Would that work?

Resources