I trying to pass data that is fetched from the server to a popup.I tried doing something like this but its not working.Please help-
{
path:'/merchant/:id',
beforeEnter: function (routeTo, routeFrom, resolve, reject) {
console.log(routeTo.params.id);
Meteor.call('getOne',routeTo.params.id,(error,result) => {
if (result) {
resolve(
{
popup: {
el:document.querySelector('#sample-popup')
}
},
// Custom template context
{
context: {
users: result,
},
}
)
}
});
} ,
},
According to the docs, you use resolve callback wrong !
You can also read this understand how to achieve this
Related
I want to update a collection called SMUProfiles, through a method called classroom.delete. I want to pull out the classroom_id from 2 places inside SMUProfiles i.e. one inside classrooms.owner which has an array of codes, and the other inside array classrooms.students.
I have successfully one the $set part, and now trying to add the $pull, but $pull doesn't seem to work.
Can we do the $set and $pull in such way?
/* Method for deleting Classroom */
'classroom.delete'(classroom_id) {
if (!this.userId) {
throw new Meteor.Error('not-authorised');
}
Classrooms.remove(classroom_id)
let classids = Classrooms.find({ owner: this.userId }).fetch().map(function(classrooms){
return classrooms._id })
//console.log(classids);
SMUProfiles.update({
owner: this.userId,
}, {
$set: {
'classrooms.owner': classids
},
$pull: {
'classrooms.students': classroom_id
}
}
)
}
You're trying to $set and $pull on the same field in the same update - the two operations conflict; so no, you can't use these operators in this way.
You could easily split this into two:
SMUProfiles.update(
{ owner: this.userId },
{ $set: { 'classrooms.owner': classids },
);
SMUProfiles.update(
{ owner: this.userId },
{ $pull: { 'classrooms.students': classroom_id },
);
See e.g. this answer
Bit of a noob question. I'm using meteor-native-mongo on the server to access the aggregate function in MongoDB, however, I'm not sure how I return and access the results on the client side. In the past subscribing and then accessing the collections on the client was pretty straightforward using the collection.find({}) function, however, I don't understand how to do it with the aggregate function. Can someone please explain.
Meteor.publish('companies', function(limit) {
db.collection('companies').aggregate([{ $group: { _id: { location: "$google_maps.geometry_location" }, companies: { $addToSet: { name: "$company_name" } }, count: { $sum: 1} } }, { $match: { count: { $gt: 1 } } }]).toArray((err, result) => {
console.log(result);
return result;
});
});
Use this.added, this.changed, this.removed from https://docs.meteor.com/api/pubsub.html#Subscription-added ...
Meteor.publish('companies', function(limit) {
var subscription = this;
db.collection('companies').aggregate([{ $group: { _id: { location: "$google_maps.geometry_location" }, companies: { $addToSet: { name: "$company_name" } }, count: { $sum: 1} } }, { $match: { count: { $gt: 1 } } }]).toArray((err, result) => {
subscription.added('companies-aggregate', 'geometry-grouping', {result: result});
});
});
// On the client:
var CompaniesAggregate = new Mongo.Collection('companies-aggregate');
// Inside a reactive context, like a helper
var result = CompaniesAggregate.findOne('geometry-grouping').result;
Naturally, to make it reactive, you'd have to know when the results of the aggregations would change. There is no automatic way to do that--you would have to resolve that logically, with your own code.
The best way to do that is to save the subscription variable in an array somewhere in a higher scope, and called changed on all the subscriptions for 'companies' for the geometry-grouping document, computing an updated result.
The commenter's solution won't be realtime; in other words, if one user makes a change to the e.g. company name or location, another user won't see those changes.
So i'm just getting started with iron-router, and I've been building a login system. It works via a .onBeforeAction hook before every route, checking if the user is logged in. However, there are a few routes I want public, so I've added an except option, as per the docs. Except the problem is it doesn't work :( can anybody see why?
Router.route('/new', function () {
name: 'new',
this.render('newComp');
});
Router.route('/c/:_id', {
name: 'compPage',
data: function() { return Comps.findOne(this.params._id); }
});
Router.route('/c/:_id/embed', function () {
name: 'embed',
this.layout('empty'),
this.render('compEmbed', {
data: function () {
return Comps.findOne({_id: this.params._id});
}
});
});
function loginFunction(){
// all properties available in the route function
// are also available here such as this.params
if (!Meteor.user()) {
// if the user is not logged in, render the Login template
if (Meteor.loggingIn()) {
this.render(this.loadingTemplate);
} else {
this.layout('empty');
this.render('login');
}
} else {
// otherwise don't hold up the rest of hooks or our route/action function
this.next();
}
}
Router.onBeforeAction( loginFunction, {
except: ['embed'] // this aint working
});
The problem seems to be in your route definition, the name param should be in the third param of Router.route(), like this (so your route actually didn't have a name, thus the except:['route.name'] doesn't work):
Router.route('/c/:_id/embed', function () {
this.layout('empty'),
this.render('compEmbed', {
data: function () {
return Comps.findOne({_id: this.params._id});
}
});
}, {
name: 'embed',
});
More info about named routes here: http://eventedmind.github.io/iron-router/#named-routes
So I have a route that sets my template
Router.route('audit', {
path: '/audit/:audit_id/',
template: 'audit',
data: function() {
if (this.ready()) {
audit_obj = Audits.findOne({_id: this.params.audit_id});
lineitems = LineItems.find(JSON.parse(audit.query));
return {
audit_obj: audit_obj,
lineitems: lineitems
}
}
},
waitOn: function () {
return [
Meteor.subscribe('lineitems', this.params.audit_id),
Meteor.subscribe('audits')
]
}
}
Now, when my user takes certain actions on the page rendered by the audit template, I would like to update the audit object and also update the data context that the page is running with. Is this possible?
Something like:
Template.audit.events({
'click .something-button': function() {
// update the data context for the current audit template.
current_context.audit_obj.something = 'new something';
}
});
Yes:
Router.route('audit', {
path: '/audit/:audit_id/',
template: 'audit',
onRun: function() {
Session.set('audit', Audits.findOne(this.params.audit_id));
Session.set('lineitems', LineItems.find(JSON.parse(audit.query)).fetch());
}
data: function() {
if (this.ready()) {
return {
audit_obj: Session.get('audit'),
lineitems: Session.get('lineitems')
}
}
},
waitOn: function () {
return [
Meteor.subscribe('lineitems', this.params.audit_id),
Meteor.subscribe('audits')
]
}
}
and
Template.audit.events({
'click .something-button': function() {
// update the data context for the current audit template.
Session.set('audit', {..});
}
});
But you'll need to decide how to handle changes that come from the server, and may interfere with changes on the front end. So a better approach might be to leave the first part of the code (router) as is:
Router.route('audit', {
path: '/audit/:audit_id/',
template: 'audit',
data: function() {
if (this.ready()) {
return {
audit_obj: Audits.findOne(this.params.audit_id),
lineitems: LineItems.find(JSON.parse(audit.query))
}
}
},
waitOn: function () {
return [
Meteor.subscribe('lineitems', this.params.audit_id),
Meteor.subscribe('audits')
]
}
}
and just change the front end to update the collection:
Template.audit.events({
'click .something-button': function() {
// update the data context for the current audit template.
Audits.update( this.data.audit_obj._id, {..} );
}
});
Of course, that will update the data on the server, too.
I would like to modify the angularFire code below (taken from the docs:
https://www.firebase.com/docs/web/libraries/angular/guide.html#section-angular-authentication)
so that if the user is not logged in it will also log the user in before page loads and the user data will be ready to use straight away.
This is the original:
resolve: {
"currentUser": ["simpleLogin", function(simpleLogin) {
return simpleLogin.$getCurrentUser();
}]
}
and this is what I have so far:
resolve: {
"currentUser": ["simpleLogin", function(simpleLogin) {
return simpleLogin.$getCurrentUser();
}],
"loginUser": ["simpleLogin", function(simpleLogin) {
return simpleLogin.$login("anonymous", {rememberMe : true} );
}]
}
but this will cause the user to be logged in each time thus resetting the ID (I think?). How do I do it conditionally so that they are only logged in if not already?
Rather than utilizing two resolve methods, I'd just chain them together. Since $login returns a promise, this is pretty smooth sailing:
resolve: {
"currentUser": ["simpleLogin", function(simpleLogin) {
return simpleLogin.$getCurrentUser().then(function(user) {
if( user === null ) {
// log in now...
return simpleLogin.$login('anonymous', {rememberMe: true});
}
else {
// logged in!
return user;
}
});
}]
}