I am new at meteor and I am having some issues. I am creating a social network app and what it basically does is signs up user and the user can post and follow others. Thats the basic functionality it does right now. I want to add something that when a user clicks on other users profile it shows that users post. But the code isnt working and doesnt show any error at all
Template
<template name="profileArea">
{{#if currentUser}}
<div id="side-profile" class="side-box">
<a class="filter-user">{{currentUser.username}}</a>
</div>
{{/if}}
<div id="side-all" class="side-box">
<a class="community">Community</a>
</div>
{{#if currentUser}}
<div id="side-like" class="side-box">
<h3>Following</h3>
<div class="boxcontent">
{{#each username in following}}
<div>
<a class="filter-user">{{username}}</a>
</div>
{{/each}}
</div>
</div>
<div id="side-likeyou" class="side-box">
<h3>Follows You</h3>
<div class="boxcontent">
{{# each followers}}
<div>
<a class="filter-user">{{username}}</a>
</div>
{{/each}}
</div>
</div>
{{/if}}
</template>
Code:
Template.profileArea.events({
'click .filter-user': function(event){
event.preventDefault();
var selectedUser = event.target.text;
Session.set('username', selectedUser);
},
'click .community': function(event){
event.preventDefault();
Session.set('username', null);
}
});
Template.postsList.helpers({
posts: function() {
//Stuff should happen here but its not -_-
var result;
if(Session.get('username')){
result = Post.find({username: Session.get('username')}, {sort:{created: -1}});
}
else{
result = Post.find({}, {sort:{created: -1}});
}
return result;
}
});
The problem in this case is that you have never actually rendered your postsList template (you have only just defined it).
If you want to actually see postsList you need to call {{> postsList }} from somewhere in your profileArea's HTML. This will render that template and then your postsList.posts helper will execute (and change reactively when Session.get('username')) changes.
Maybe add this after the 'Follows You' section of the profile.
<div id="side-posts" class="side-box">
<h3>Posts</h3>
<div class="boxcontent"> {{> postsList }} <div>
</div>
Related
i am following the following error when trying to filter the images posted by a certain user
the error :
Exception from Tracker recompute function:
meteor.js?hash=857dafb4b9dff17e29ed8498a22ea5b1a3d6b41d:1059 ReferenceError: $el is not defined
at destroyApi (stars_rating.js:98)
at Blaze.TemplateInstance.Template.starsRating.destroyed (stars_rating.js:132)
at template.js:124
at Function.Template._withTemplateInstanceFunc (template.js:493)
at fireCallbacks (template.js:120)
at Blaze.View.<anonymous> (template.js:226)
at fireCallbacks (view.js:276)
at Object.Tracker.nonreactive (tracker.js:603)
at view.js:273
at Object.Blaze._withCurrentView (view.js:533)
find here the js click event i wrote when clicking on the user username :
'click .js-set-image-filter': function(event){
Session.set("userFilter", this.createdBy);
}
find here the template helper code:
images: function(){
if(Session.get("userFilter")){
return TasksCollection.find({createdBy:Session.get("userFilter")},{sort :{cretedOn:-1 ,rating:-1}});
}
else{
return TasksCollection.find({},{sort :{cretedOn:-1 ,rating:-1}});
}
},
find here the template code:
<template name="hello">
{{#if currentUser}}
<button class="js-show-image-form btn btn-success">show</button>
{{/if}}
<div class="row">
{{#each images}}
<div class="col-xs-6 col-md-3" id="{{_id}}">
<div class="thumbnail">
<img class="js-image crop-img" src="{{img_src}}" alt="{{imd_alt}}"/>
<div class="caption">
<h3>Rating : {{rating}}</h3>
<p>{{imd_alt}}</p>
<p> User:
{{getUser createdBy}}
</p>
<p> {{>starsRating mutable=true class="js-rate-image" id=_id}}</p>
<button class="js-del-image btn btn-warning">Delete</button>
</div>
</div>
</div>
{{/each}}
</div>
</template>
I have figured out half of this, but I'm not sure how to completely fix it.
The Exception from Tracker error is caused by using '#' inside the href of
<a href="" class="js-set-image-filter">{{getUser createdBy}} .
Now when I click a user my page flashes and resets to all images, which seems to be another issue altogether.
I have the following template code:
<template name="dashboard">
<div class="content-container-with-sidebar clearfix">
<div class="dashboard-container">
{{#if Template.subscriptionsReady}}
<div id=masonry-grid class="masonry-grid clearfix">
{{> timePieChartCard}}
{{> expensePieChartCard}}
{{> HighlightsCard}}
{{> initializeMasonry}}
</div>
{{/if}}
</div>
</div>
</template>
I'd like to run the initializer for the masonry library after all the templates and their subscriptions/helpers load within the main dashboard template.
Each card has code similar to this:
<template name="HighlightsCard">
{{#if highlightsExist}}
<div class="col-md-6 masonry-grid-item">
<div class="card highlights-card">
</div>
</div>
{{/if}}
</template>
Template.highlightsCard.onCreated(function() {
this.autorun(() => {
this.subscribe('userOwnClientHighlightsData');
});
});
Template.highlightsCard.helpers({
highlights() {
return Highlights.find({}, {
limit: 4,
sort: {createdAt: -1}
}).fetch();
},
highlightsExist() {
return (Highlights.find().count() > 0);
}
});
I currently am setting a session that increases when each onRendered is run within the card templates, but once they all render their contents have still not loaded. I need the class masonry-grid-item to be visible in order for me to initialize masonry.
What's the best way to get a similar result as jquery's $(document).ready() ?
Update: each individual card in the dashboard template has it's own subscription to a different dataset.
Look at Tracker.afterFlush
Schedules a function to be called during the next flush
For example:
Template.dashboard.onRendered(()=>{
Tracker.afterFlush(()=>{
...your code here
});
});
If I understand the problem correctly, you want to initialize your component after the subscription is complete and after all sub-templates (that also depend on the subscription data) are rendered.
Since I don't know what your JavaScript looks like, here is an example of what you can try.
Template.dashboard.onRendered(function() {
this.isReady = new ReactiveVar(false);
this.subscribe('subscriptionName', () => {
this.isReady.set(true);
Tracker.afterFlush(() => {
// Initialize component here
});
});
});
Template.dashboard.helpers({
isReady: () => {
return Template.instance().isReady.get();
},
});
And then use the isReady ReactiveVar in your template. In this case, isReadymay not be necessary (e.g. you could probably use the Template.subscriptionsReady helper), but I like to have explicit control of when to render incase my logic gets more complex in the future. Note, I removed {{> initializeMasonry}} because it looked like you were attempting to initialize your component via a helper.
<template name="dashboard">
<div class="content-container-with-sidebar clearfix">
<div class="dashboard-container">
{{#if isReady}}
<div id=masonry-grid class="masonry-grid clearfix">
{{> timePieChartCard}}
{{> expensePieChartCard}}
{{> HighlightsCard}}
</div>
{{/if}}
</div>
</div>
</template>
The callback to Tracker.afterFlush will get executed on the next Blaze render cycle, which will be after your sub-templates are rendered.
I want to break a big web page up into bite-size chunks for the user, so that they are not overwhelmed by the size of the page / the amount of information they have to enter (all at once, anyway).
I'm using Meteor, and would like to know how to accomplish this with that platform.
The first idea that comes to mind is to create a separate template for each "sub page" I want to show the user, and then present the templates one after another. I'm thinking maybe something like this:
<body>
<h2>Thirteen Ways of Looking at a Duckbilled Platypus</h2>
<br/>
<br/>
<div class="container">
{{> whizzardBlizzard}}
</div>
</body>
<template name="whizzardBlizzard">
<form>
{{#if firstStep}}
{{> firstStepTemplate}}
{{/if}}
{{#if secondStep}}
{{> secondStepTemplate}}
{{/if}}
{{#if thirdStep}}
{{> thirdStepTemplate}}
{{/if}}
<input type="submit" value="Submit" class="button">
</form>
</template>
<template name="firstStepTemplate">
<h2>Step 1</h2>
</template>
<template name="secondStepTemplate">
<h2>Step 2</h2>
</template>
<template name="thirdStepTemplate">
<h2>Step 3</h2>
</template>
The submit event handler would be a template event method that would save the data entered at each step and update the value of a "counter", something like:
Template.whizzardBlizzard.events({
"submit form": function (event) {
//event.preventDefault(); <= should this be uncommented?
// save the vals to a new document in a collection
Session.set('stepNum', Session.get('stepNum') + 1);
}
});
The "firstStep," "secondStep," etc. would perhaps be template helpers, such as:
Template.whizzardBlizard.helpers({
firstStep: function() {
return (Session.get('stepNum') == 1);
},
secondStep: function() {
return (Session.get('stepNum') == 2)
},
thirdStep: function() {
return (Session.get('stepNum') == 3)
}
. . . // etc.
});
...but am not sure if this will really fill the bill or be the best approach. Is there a "blessed" way of doing this with Meteor, or an accepted pattern?
I am an Ember newbie and can't get my head around how to run events on specific elements populated via records on my ember model.
Here is my Template
{{#each user in model }}
{{#each activecredit in user.activecredits}}
<div class="col-lg-2 hive-credit-box active-credit">
<div class="credit-brandname">
{{activecredit.Brandname}}
</div>
<div class="credit-brand-image-container">
<img src="http://localhost:3000/{{activecredit.Imglocation}}" class="credit-image"/>
</div>
<div class="hive-credit-percent"><img class="hive-filled-container" src="imgs/hivefilled9.png"/></div>
<div class="hive-credit-dollars">$xx.xx</div>
<div {{bind-attr class=activecredit.Brandname}} {{action 'enableTrade'}}><img src="imgs/trade_button.png" class="credit-trade-button" /></div>
<div class="credit-brand-amount">
xx%
</div>
<!-- Trade button click dropdown -->
{{#if isSelected}}
<div class="hivetrade">
<div class="arrow_box">
Hi there
</div>
<div class=""></div>
</div>
{{/if}}
</div>
{{/each}}
{{/each}}
Now I want to show a drop down on each element on click of a button .
When I set the enableTrade action , all dropdowns of all the divs show up.
actions:{
enableTrade:function(){
this.set('isSelected',true);
}
}
How do I enable only the dropdown in the particular div that was created.
I suppose I need to bind certain attributes to each div,but how do I access which div was clicked in my controller?
Any help would be appreciated .
Thanks
You can pass params through the action helper, and use them to set isSelected on the appropriate item.
{{#each model as |user| }}
{{#each user.activeCredits as |activeCredit|}}
<button {{action 'enableTrade' activeCredit}}>Enable Trade</button>
{{#if activeCredit.isSelected}}
<div class="hivetrade">Hello World</div>
{{/if}}
{{/each}}
{{/each}}
To handle it:
actions:{
enableTrade:function(credit) {
credit.set('isSelected',true);
}
}
If you need to allow only one credit to be selected at a time, your controller and action could be modified like this:
selectedCredit: null,
actions:{
enableTrade:function(credit) {
// unselect the previously selected credit
if (this.get('selectedCredit')) {
this.set('selectedCredit.isSelected', false);
}
// select, and cache the selection choice
credit.set('isSelected',true);
this.set('selectedCredit', credit);
}
}
So, I've been working with Discover Meteor, and I'm having problems.
I'm trying to insert what content inputted in summernote into mongo but I'm having a few problems.
post_submit.html
<div class="form-group {{errorClass 'content'}}">
<textarea class="form-control" name="content" id="summernote"></textarea>
</div>
post_submit.js
var post = {
url: checkURLPrefix( $(e.target).find('[name=url]').val() ),
title: $(e.target).find('[name=title]').val(),
content: $(e.target).find('[name=content]').val()
};
lib/posts.js (will say Match Failed error when submitting)
meteor.methods({
postInsert: function(postAttributes) {
check(this.userId, String);
check(postAttributes, {
title: String,
url: String,
content: function(content){$('[name=content]').html($('#summernote').code());}
});
I've tried content: String to input the data into mongo. It would work but when I tried to load {{content}} in the post_page.html file, it would just show the unrendered HTML codes. {{{content}}} would show to content properly rendered but would mess up the functionality of the sorting system based on votes.
I'm really lost here and I wish I could find a solution soon.
Thank you in advance!
EDIT1: Here is my post_page.html and what I see when I insert content: String and load with {{content}}
<template name="postPage">
{{> postItem}}
<div class="col-md-12" style="background:blue;">
{{content}}
</div>
<ul class="comments">
{{#each comments}}
{{> commentItem}}
{{/each}}
</ul>
{{#if currentUser}}
{{> commentSubmit}}
{{else}}
<p>Please log in to leave a comment.</p>
{{/if}}
</template>
http://i.imgur.com/Fm0CXAN.png
First: you should use summernote in a div, not a textarea.
And in post_submit.js you have to leave it like this:
var post = {
...
content: $(e.target).find('#summernote').code()
};
In your post_page.html use triple brackets, because its HTML.
<div class="col-md-12" style="background:blue;">
{{{content}}}
</div>