Meteor using different Sessions with {{#each}} for click event - javascript

I want to use different Sessions for a specific click event within a {{#each}} block. The problem is that HTML elements will be displayed for all {{#each}} block members, but I only want it for the one, a user performs the click event on.
Here is my code:
...
{{#each articles}}
<tr id="{{_id}}" class="article-row">
<td class="articles">
{{> article}}
</td>
</tr>
{{/each}}
...
<template name="article">
{{#if editArticle}}
<div class="input-group">
<span class="input-group-addon">Edit article</span>
<input type="text" name="edit-article-input" class="form-control" placeholder="Name your article." value="{{title}}">
<span class="input-group-btn">
<button class="btn btn-success glyphicon glyphicon-ok edit-article-submit" data-type="last"></button>
</span>
</div>
{{else}}
<div class="panel panel-default article">
<div class="panel-heading">
<h3 class="panel-title">{{title}}</h3>
</div>
<div class="panel-body">
<button class="glyphicon glyphicon-pencil btn btn-default btn-xs edit-article"></button>
</div>
</div>
{{/if}}
</template>
Helper methods and events:
Template.article.helpers({
editArticle: function() {
return Session.equals('editArticle', true);
}
});
In the template with the {{#each}} block I use this helper method:
'click .edit-article': function(e, t) {
e.preventDefault();
Session.set('editArticle', true);
}
Now the problem is, that if I click on the button .edit-article the {{#if editArticle}} block appears on every article. I just want it for the one I clicked on.
Any help would be greatly appreciated.

This is a perfect example of how Session isn't always the right tool for the job when it comes to template reactivity. Unless you actually need to know which article is being edited outside of the template, I'd strongly recommend using a ReactiveVar or ReactiveDict rather than a global variable like Session. It's a little more to write but, in my opinion, a much more encapsulated and elegant solution. Here's the outline of the code you'd need:
Template.article.created = function() {
this.isEditing = new ReactiveVar(false);
};
Template.article.events({
'click .edit-article': function(e, template) {
e.preventDefault();
template.isEditing.set(true);
},
submit: function(e, template) {
e.preventDefault();
template.isEditing.set(false);
}
});
Template.article.helpers({
editArticle: function() {
return Template.instance().isEditing.get();
}
});
Note that you'd need to do meteor add reactive-var for this to work. For more details, see my post on scoped reactivity.

Related

Can't pull .attr() from button generated via handlebars

I'm in the process of building a web scraper for a homework assignment involving Express, Mongoose, Cheerio/axios, and Handlebars. My "/" route grabs the Mongoose objects and handlebars loads them to the page in individual cards. A save button is generated with an attribute data-id={{_id}}' in these cards. I'm trying to access the attribute with jQuery when it's pressed to save it to another collection but $(this) is returning undefined.
js
$(document).ready(function () {
$("#artDiv").on("click", ".save", (event) => {
event.preventDefault();
let id = $(this).attr("data-id");
console.log($(this).data("id"));
console.log(id);
})
});
html
<div id="artDiv" class="container">
{{#obj}}
{{#each .}}
{{#if headline}}
<div id="articleCard" class="card">
<h5 class="card-header">{{altHead}}</h5>
<div class="card-body">
<h5 class="card-title">{{headline}}</h5>
<p class="card-text">{{desc}}</p>
Visit
<button data-id="{{_id}}" data-control="saveBtn" type="button" class="btn btn-success save">Save</button>
</div>
</div>
{{/if}}
{{/each}}
{{/obj}}
</div>
If you want to have your clicked element in $(this), you cannot use arrow functions. You have to use $("#artDiv").on("click", ".save", function (event) { ... });.

getValue not working on custom template

I've been able to make my own field, using a costum template. This field consist in a textField followed by button at the end, on the same line, but I'm confronted to an issue.
When I'm using form.getValue(), it does return the original values, I mean, if I modify 1 field and then do a getValue(), the modification won't be visible and I will still get the value I had when loading the form.
I'm pretty sure there is a problem with my template but I can't figure what to do ! :(
Here is my templates code :
{% raw %}
<script type="text/x-handlebars-template" id="input-group-addon-template">
<div class="input-group">
<input type="{{inputType}}" value="{{data}}" id="{{id}}" {{#if options.placeholder}}placeholder="{{options.placeholder}}"{{/if}} {{#if options.size}}size="{{options.size}}"{{/if}} {{#if options.readonly}}readonly="readonly"{{/if}} {{#if name}}name="{{name}}"{{/if}} {{#each options.data}}data-{{#key}}="{{this}}"{{/each}} {{#each options.attributes}}{{#key}}="{{this}}"{{/each}}/>
<div class="input-group-btn" id="{{id}}-basic-btn">
<button class="btn btn-default" id="{{id}}-button" onclick="test(event)" >
<i {{#if options.readonly}}class="fa fa-lock"{{else}}class="fa fa-unlock"{{/if}}></i>
</button>
</div>
</div>
</script>
{% endraw %}
<script>
With some help, I've been able to get it to work. So I just had to modify the template, new template :
<script type="text/x-handlebars-template" id="input-group-addon-template">
<div class="input-group">
{{#control}}{{/control}}
<div class="input-group-btn" id="{{id}}-basic-btn" >
<button class="btn btn-default" id="{{id}}-button" onclick="click_function(event)" >
<i {{#if options.readonly}}class="fa fa-lock"{{else}}class="fa fa-unlock"{{/if}}></i>
</button>
</div>
</div>
</script>
So the big difference is that we don't precise the "input-type" anymore so that we don't override all usefull function as getValue etc.
Feel free to add some explication ! :D

I cant seem to find the error in Meteor

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>

How to show an icon on click in meteor?

I am building an application in a meteor and I have a below code in the template.
<h3>
<b>
<a class="viewed" href="/jobdetails/{{_id}}">{{title}}</a>
</b>
<span class="job-type part-time">Part Time</span>
</h3>
<div id="eyeIcon">
<span class="glyphicon glyphicon-eye-open" style="color:green"></span>
</div>
I have to display the glyphicon eye icon on click of a href tag and storing them into a collection. How can I do that? I am new to the meteor. Can anyone help me how can we do it using Meteor. Thanks in advance.
<h3>
<b>
<a class="viewed" href="/jobdetails/{{_id}}">{{title}}</a>
</b>
<span class="job-type part-time">Part Time</span>
</h3>
{{showIcon}}
<div id="eyeIcon">
<span class="glyphicon glyphicon-eye-open" style="color:green"></span>
</div>
{{/if}}
Template.yourTemplate.helpers({
'showIcon': function() {
return Session.get('showIcon');
},
});
Template.yourTemplate.events({
'click .viewed': function(event, instance) {
event.preventDefault();
Session.set('showIcon', true);
},
});
Please note that I have used session to persist your data throughout the app. If you also want to retain this value permanently than you can use collections.
Also, if you to just retain it's value to be persisted on page refresh also, then you can use Session.setPersistent (https://github.com/okgrow/meteor-persistent-session) instead of Session.set
Start by hiding your #eyeIcon div by default. For example, add the following to /client/main.css:
#eyeIcon {
display: none;
}
Then leverage the Blaze Template event system to show the div when the link is clicked. So in your Template:
Template.yourTemplate.events({
'click .viewed'(event, instance) {
event.preventDefault();
instance.$('#eyeIcon').show();
},
});

Backbone.js audio control

I have a Backbone view, it uses an html template, placed on the page:
<script type="text/template" id="webphone-template">
<audio id="audio-ringtone" src="{% static "prime_app/assets/audio/ringtone.mp3" %}"></audio>
<div class="well">
<p class="text-muted text-center"><%= status %></p>
<div class="text-center">
<button id="btn-webphone-answer" class="btn btn-success">
<i class="fa fa-phone"></i>
</button>
<button id="btn-webphone-terminate" class="btn btn-danger">
<i class="fa fa-phone"></i>
</button>
</div>
</div>
</script>
My view has method ring(), which looks like this:
ring: function() {
$("#audio-ringtone").get(0).play();
}
But when this method is invoked audio doesn't play, no errors in JS console, the audio element is chosen correctly. What's the problem?
Well i dont know how your whole view works, if you add it i can modify the code, but i got it to work fairly easy. Again, i need to see your view code to see what youre doing wrong.
View = Backbone.View.extend({
template: _.template($('#webphone-template').html()),
events: {
'click #btn-webphone-answer': 'ring'
},
initialize: function(opt) {
// attach to the main body
$(opt['main']).append(this.el)
this.status = 'paused';
this.render();
},
ring: function() {
$(this.el).find('#audio-ringtone')[0].play()
},
render: function() {
$(this.el).append(this.template({status: this.status}));
return this;
}
});
new View({ main: $('body') });
works: http://jsfiddle.net/hLero5rd/
Finally, there was the following problem: audio-tag is in my view's element, when i call render(), it completely replaces all the HTML inside element, so if there is audio-element it just gets removed and the sound doesn't play anymore.

Categories