subscribe on click event is not working - meteor

My doc strucure:
"_id" : "p5NXQZd5b5dbMrECW",
"feed_id":"xfsfasfsadfdfafs",
"comments" : [
{
"user" : "fzkhiAArD4mgAAjbL",
"comment" : "First comment",
"commentedAt" : 1422416042795
},
{
"user" : "fzkhiAArD4mgAAjbL",
"comment" : " second comment",
"commentedAt" : 1422416071633
},
{
"user" : "fzkhiAArD4mgAAjbL",
"comment" : " third comment is so longgggggggggggggggggggggggggggggggggggg",
"commentedAt" : 1422416087707
},
.......
....
}
my code,Initially I'm sending 3 comments to the user using publish-composite
Meteor.publishComposite('hub_feed',function(hubid){
return {
find: function() {
return HubFeeds.find({hub_id:hubid});
},
children: [
{
find: function(feed) {
var res=FeedHits.findOne({feed_id:feed._id});
if(res){
if(_.has(res,"comments")){
return FeedHits.find({_id:res._id},{fields: {comments:{$slice: -3}}});
}
}
}
}
]
}
});
I'm subscribing in the client
Meteor.subscribe("hub_feed")
which is working fine and I displayed the 3 comments.
Now on click event I want to load more comments,so created another publish function
Meteor.publish("getExtraFeedComments",function(noOfComments,feedid){
var required=noOfComments+10;
..........
return FeedHits.find({feed_id:feedid},{fields: {comments:{$slice: -required}}});
});
I'm subscribing to this publish function,when user clicks on load more comments button
'click #loadMoreComments':function(){
var hasComments=FeedHits.findOne({feed_id:this._id});
if(hasComments && _.has(hasComments,"comments")){
var noOfComments=hasComments.comments.length;
var handle=Meteor.subscribe("getExtraFeedComments",noOfComments,this._id);
if(handle.ready()){
console.log('ready');
console.log(FeedHits.find().fetch());
}
}
}
Here is my issue, In console I'm not getting ready and also I'm getting only 3 comments.
why is this subscribe onclick event is not working.
Nte:In server before publishing I've checked the results .
It is displaying 5 comments,but in client it is showing only 3 comments
...........
......
console.log(FeedHits.find({feed_id:feedid},{fields: {comments:{$slice: -required}}}).fetch())
return FeedHits.find({feed_id:feedid},{fields: {comments:{$slice: -required}}});
Edit
with callback function
Meteor.subscribe("getExtraFeedComments",noOfComments,this._id,function(){
console.log(FeedHits.findOne({feed_id:self._id}));
});
I'm getting 3 values only I'm not getting more values

It looks like you are trying to do a synchronous call from the client:
var handle=Meteor.subscribe("getExtraFeedComments",noOfComments,this._id);
In Meteor the client is never synchronous, so in this case 'handle' will not return what you expect. It probably will be null.
In order to accomplish what you are trying to do, you need a callback in your subscribe function.
Meteor.subscribe("getExtraFeedComments", function(){ /* sub ready here */})
Hope that helps.

Related

Getting Cannot execute "delete" on "Article" in CASL JS

I'm learning CASL JS and trying to delete an article with a condition but getting this error Cannot execute "delete" on "Article". Here is the CodeSandBox Link.
Here is the sample code:
const { createMongoAbility, ForbiddenError } = require("#casl/ability");
const rules = [
{
action: "read",
subject: "Article"
},
{
inverted: true,
action: "delete",
subject: "Article",
conditions: { published: true },
reason: "You are not allowed to delete this article"
}
];
const ability = createMongoAbility(rules);
// this can be pulled from a database
class Article {
constructor(attrs) {
Object.assign(this, attrs);
}
}
const anotherArticle = new Article({
authorId: 2,
published: false,
content: "Lorem Ipsum"
});
try {
// checking ability before taking some action
ForbiddenError.from(ability).throwUnlessCan("delete", anotherArticle);
} catch (error) {
console.log(error.message); // throwing `Cannot execute "delete" on "Article"`
}
Please help me out. Thanks
The creator of CASL JS has answered this:
you declared that it's not possible to delete published articles but you have never said that it's possible to delete articles at all. That's why you get the error
So this means that I already declared inverted permission and it's not possible to delete articles.

Fetching data inside a template's event handler

I want to test a few things that regards some data I have stored stored in a collection called exams. This is my code
Template.Examinations.events({
'click .reactive-table tr': function() {
Session.set('selectedPersonId', this._id);
var cursor = Exam.findOne(Session.get("selectedPersonId"));
if (!cursor.count()) return;
cursor.forEach(function(doc){
console.log(doc._id);
});
},
});
Every time I run the code by clicking a row, I get the error
Uncaught TypeError: cursor.count is not a function
Why am I getting this error?
Update
{
"_id" : "RLvWTcsrbRXJeTqdB",
"examschoolid" : "5FF2JRddZdtTHuwkx",
"examsubjects" : [
{
"subject" : "Z4eLrwGwqG4pw4HKX"
},
{
"subject" : "fFcWby8ArpboizcT9"
}
],
"examay" : "NrsP4srFGfkc5cJkz",
"examterm" : "5A5dNTgAkdRr5j53j",
"examclass" : "gYF2wE4wBCRy9a3ZC",
"examname" : "First",
"examdate" : ISODate("2016-05-07T22:41:00Z"),
"examresultsstatus" : "notreleased"
}
You are using Exam.findOne which will return an object but not array, which is causing the error cursor.count is not a function. You should use Exam.find({}).fetch() and then you can get the count form the result.
Template.Examinations.events({
'click .reactive-table tr': function() {
Session.set('selectedPersonId', this._id);
var examsArray = Exam.find({ personId: this._id}).fetch();
examsArray.forEach(function(doc){
console.log(doc._id);
});
},
});

Why I can see view1 after I triggering navigation to view2 (integration testing)

I have some questions about integration testing (OPA5, sapui5): I have created simple project which has 2 views (View1.view.xml and View2.view.xml), and I have sap.m.Button on the first view. After I press this button I'll navigate to the second view. So I have implemented OPA5 tests to check this functionality. So now I'm simulating user's click at button and Navigation is working properly. But If I want to check visibility View1.view.xml after triggering navigation I will get "test passed" result! I guess that tests are executed asynchronously that is why I have had this results. And how can I catch moment when test will finish to execute next?
UnexpectedbehaviorJourney.js
QUnit.module("Unexpected behavior");
opaTest("Why do I see View1.view after Navigation was pressed?",
function (Given, When, Then) {
// Arrangements
Given.iStartMyApp();
//Actions
When.onTheAppView.iLookAtTheScreen().
and.iPressNavigateButton();
// Assertions
Then.onTheAppView.iShouldSeeView1AfterTriggeringNavigation();
// and.iTeardownMyAppFrame();
});
UnexpectedBehavior.js
actions : {
iPressNavigateButton : function () {
return this.waitFor({
id : "idButton",
viewName : "View1",
actions: new Press(),
errorMessage : "Button control wasn't pressed"
});
}
},
assertions : {
iShouldSeeView1AfterTriggeringNavigation : function () {
return this.waitFor({
id : "idView1",
viewName : "View1",
success : function () {
ok( true, "Why I can see View1.view?");
},
errorMessage : "Navigation has worked as expected!"
});
}
}
View1.controller.js
return Controller.extend("InvestigateOPA.controller.View1", {
onPress: function() {
this.getOwnerComponent().getRouter().navTo("appView2");
}
});
Do you have any idea how can I prevent this behavior?
Shouldn't the assertion be a check for View2 visibility?
else try something like below
nb. you can use Qunit and Sinon functions like a delay/timer or a native promise etc.
iShouldNotSeeView1AfterTriggeringNavigation : function () {
return this.waitFor({
id: "app",
viewName: "App",
check: function(oApp) {
return oApp.getCurrentPage().getId() !== "__component0---View1"
},
success: function() {
ok( true, "View1 not current page");
},
errorMessage: "Navigation has not worked as expected!"
});
I have found that the one way to solve my problem is set "transition" property to "show":
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"transition": "show",
"viewPath": "InvestigateOPA.view",
"controlAggregation": "pages",
"controlId": "app"
},
In this case there is no visual delay when one view change another, so my OPA tests will work correctly.
p.s. thx a lot for your ideas!

Why isn't my subscription adding data to Meteor.user()?

I'm publishing this user information (as a test FYI, not going to reveal all this information in production)
Meteor.publish('user.private', function userPrivate() {
if (!this.userId) {
return this.ready();
}
return Meteor.users.find({
_id: this.userId
}, {
fields: {
'services.microsoft': 1,
'services.google': 1
}
});
});
I'm subscribing like this:
Template.App_body.onCreated(function appBodyOnCreated() {
this.subscribe('user.private');
});
I've confirmed that this exact query works and returns data using meteor mongo, yet this information does not appear in the Meteor.user() call on the client. What am I doing wrong?
try changing the publication name to null to make it automatically publish.
Meteor.publish(null, function () {
return Meteor.users.find(this.userId, {
fields: { /** ... fields here */ }
});
});

In Meteor when trying to access an attribute, I get TypeError: Cannot read property in the console. But the site is working

When trying to read an attribute, meteor gives me a TypeError: Cannot read property 'featuredImage' of undefined error in the browser console. But it reads featuredImage and the site is working fine. How can I get rid of this error? Is it happening because my subscriptions are not yet ready? Is that's the case, how to fix it? (PS : Im using the flow router so I can't wait for subscriptions in the router)
My template code :
Template.About.helpers({
page: () => {
return findPage();
},
featuredImage: () => {
var thisPage = findPage();
return Images.findOne({
"_id": thisPage.featuredImage
});
}
});
function findPage() {
return Pages.findOne({
slug: 'about'
});
}
The router code :
FlowRouter.route('/about', {
name: 'about',
subscriptions: function() {
this.register('page', Meteor.subscribe('pages', 'about'));
this.register('image', Meteor.subscribe('images'));
},
action() {
BlazeLayout.render('MainLayout', {
content: 'About'
});
setTitle('About Us');
},
fastRender: true
});
The subscription is probably not ready yet. FlowRouter provides a utility for dealing with this, your helpers should look like this:
Template.About.helpers({
page: () => {
// If you only need a specific subscription to be ready
return FlowRouter.subsReady('page') && findPage() || null;
},
featuredImage: () => {
// Ensure ALL subscriptions are ready
if ( FlowRouter.subsReady() ) {
var thisPage = findPage();
return Images.findOne({
"_id": thisPage.featuredImage // Probably should be thisPage.featuredImage._id
});
}
return null;
}
});
However, for maximum performance, you should use if (FlowRouter.subsReady('page') && Flowrouter.subsReady('image')) rather than FlowRouter.subsReady() since if you have other pending subscriptions which are large, it will wait for those even though you don't need them.

Resources