Meteor combined with Session.set and jQuery in one call - javascript

I'm trying to get something very basic to work in Meteor, where when the user clicks a button a Session.set() is called and then a div is shown. The problem is that if I don't call the Session.set() the behaviour is as expected where the div is shown upon clicking the button. But once I include the Session.set() i need to click twice before the message is actually show. To make sure the behaviour can be reproduced make sure the page is a clean load and not a Meteor refresh!
The code for the HTML is:
<head>
<title>test</title>
</head>
<body>
{{> home}}
</body>
<template name="home">
<div>
<input type="button" id="addButton" value="add">
</div>
{{> popup}}
</template>
<template name="popup">
{{#with messageHelper}}
<div id="messageDiv" style="display: none">
message is {{message}}
</div>
{{/with}}
</template>
And here is the Javascript that makes it tick.
Template.home.events({
'click #addButton': function(){
// **** if this line is commented out, it will work
Session.set("messageHelper", {message: 'HERE'});
// ****
$('#messageDiv').show();
}
});
Template.popup.helpers({
messageHelper: function(){
return Session.get("messageHelper");
}
});

I think the changed session variable rerenders your template in its original state which sets style="display: none". The problem is discussed here. The solution there is to reorganise your template so the reactivity is not in the template where display is being toggled.
An easier solution might be just to use handlebars #if helper to display your template whenever there is a message:
<template name="popup">
{{#with messageHelper}}
{{#if message}}
<div id="messageDiv">
message is {{message}}
</div>
{{/if}}
{{/with}}
</template>
No need for .show() in the event handler then.

Related

Meteor Blaze tab key event

This Meteor code does not print to console the event.which so as to use tab key event when tabbing out of an editable div.
Why editable div? Because I can style part of the string which is not allowed in input element.
BTW: Where do I find a list of the events types for Meteor Blaze. There site only lists a very limited events. Other DOM events are available as well, but...
I tried some blur and onblur for no avail.
How can I fire a tab key event on an editable div? Thanks
//client/main.js template evnet
'onblur #vin'(e){
console.log(e.which) //prints nothing
let vin = e.target.value
}
<div class="body">
<div id="vin" class="editable" contenteditable="true">{{vehicle.vin_a}}<span id="vinb">{{vehicle.vin_b}}</span><span id="vin4">{{vehicle.vin4}}</span></div>
<input type="text" placeholder="make, modle, date">
</div>
It works for me!
Here is a minimal, reproducible example:
main.html:
<head>
<title>b</title>
</head>
<body>
{{> info}}
</body>
<template name="info">
<div id="vin" class="editable" contenteditable="true">
Edit me
</div>
</template>
main.js:
import { Template } from 'meteor/templating';
import './main.html';
Template.info.events({
'blur #vin'(event, instance) {
console.log('blur!', event);
}
});
Maybe you defined the event on the wrong template?

Meteor: Setting handlebars variable true/false

I'm pretty new to this whole handlebars concept but basically I want to be able to set a variable to true on the click of a button and then back to false again from submitting a form in the template that is displayed only if the variable is true.
For the body I have the following code:
<body>
{{#if notification}}
{{> notifier}}
{{else}}
{{#if currentUser}}
{{> dashboard}}
{{else}}
{{> login}}
{{/if}}
{{/if}}
</body>
Lets say I have a link in the dashboard which runs in the client js with the id noticationTestLink, what would I put in the dashboard events for the following function:
'click #noticationTestLink' : function(event) {
event.preventDefault();
}
if I wanted to set the notification variable to true (this is the notification that I refer to in the body).
I'm pretty sure I could figure out the rest if I know how to do this. Please excuse my lack of experience/knowledge in using handlebars. I'm also pretty new to just using Meteor. Thanks in advance!
PS: I may be completely on the wrong track with this, but that's why I'm asking the question.
Hard to believe no one has answered this question yet!
js:
'click #noticationTestLink' : function(event) {
event.preventDefault();
Session.set('notification',true);
}
Template.myTemplate.helpers({
notification: function(){
return Session.get('notification');
}
});
You need a template, Meteor will wrap it with <body>...</body> automatically:
<template name="myTemplate">
{{#if notification}}
{{> notifier}}
{{else}}
{{#if currentUser}}
{{> dashboard}}
{{else}}
{{> login}}
{{/if}}
{{/if}}
</template>

Handlebars render only some elements

I have the following handlebars template:
<script type="text/x-handlebars" data-template-name="index">
{{log model}}
<button {{action 'getSuggestion'}}>Get suggestion</button>
{{log suggestion}}
{{#if suggestion}}
<p>There is a suggestion</p>
{{else}}
<p>NO suggestion</p>
{{/if}}
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</script>
Currently, the two log work as expected, but the button between them is not rendered.
A while ago I've added another <p>text</p> right in the beginning of the template and again, it didn't render.
Do you have any idea why? And is there a specific way to debug Ember applications? I find Handlebars extremely unpredictive, with elements being rendered or not after no specific reason, and with no errors shown...
The thing was pretty simple: I was using a somewhat older version of Ember.js. Updating to the latest one made everything work again.

Making divs clickable - Ember view for action on multiple elements

I am developing a Cordova application with help from Ember. I have many dynamic elements in my application. These are Bootstrap thumbnails that link to other routes when clicked.
I want to make these thumbnails clickable. If I use Views, I will have to write unique views for all the thumbnails.
I have heard about mixins. Can a general View be defined that will :
Pass a model
Render a template for a route with the model
In other words, since each view semantically performs the same action, I want to be able to do something similar to
{{#each}}
{{#view App.AllView this}}
.
{{/view}}
{{/each}}
in the template and in the view :
App.AllView = Ember.View.extend({
click: function(evt, model){
this.controllerFor('route').set('content', model);
this.transitionTo('route');
}
});
UPDATE
Following #givanse's answer, I made the following component
<script type="text/x-handlebars" data-template-name="components/thumbnail-view">
<div {{bind-attr class=class}}>
<div class="thumbnail">
<div class="caption">
{{name}}
</div>
<img {{bind-attr src=image }}>
</div>
</div>
</script>
and used it in my template :
<script type="text/x-handlebars" data-template-name="types">
<div class="row">
{{#each model}}
{{thumbnail-view action="goToCategory" class="col-xs-12" param=this name=name image=image}}
{{/each}}
</div>
</script>
with an Ember component :
Pioneer.ThumbnailViewComponent = Ember.Component.extend({
click: function(){
this.sendAction('action', this.get('param'));
}
});
The action goToCategory is defined in my ApplicationRoute
Hope this helps someone!
What you need is Components, something like:
<script data-template-name="index">
{{#each}}
{{img-thumbnail imgId="id/path/name"}}
{{/each}}
</script>
<script data-template-name="components/img-thumbnail">
{{! whatever you need to make your thumbnail }}
</script>
App.ImgThumbnailComponent = Ember.Component.extend({
// handle events, classes, etc.
});
See:
http://emberjs.com/guides/components/
http://emberjs.com/api/classes/Ember.Component.html

set focus in an ember application

I want to be able to set the focus to a textarea as a result of a mouse click not in that task area.
As a minimal example, let's say that I'm starting with a text and if you click on it, it gets replaced with a textfield. I can achieve this by a handlebars script:
<script type="text/x-handlebars">
{{#if isActive}}
{{view Ember.TextField}}
{{else}}
<p {{action foo}}> Click Here to Enter text </p>
{{/if}}
</script>
with a controller of
App.ApplicationController = Ember.Controller.extend({
isActive: false,
foo: function(){
this.set("isActive", true);
}
});
This works to create the textfield on the click, but does not give focus to that text area (it takes a second click to be able to actually enter text).
Is there a good way to achieve this end? I could do something hacky by setting an ID in the template and selecting it with jquery, but that seems inelegant.
Furthermore, to reduce the didInsertElement and this.$().focus(); which can seem as though you're mixing jQuery into your Ember modules -- and something I hate doing, you can use the Ember.JS way of specifying additional attributes for the Ember.TextField.
We can specify that we're interested in the HTML5 autofocus attribute:
Ember.TextSupport.reopen({
attributeBindings: ["autofocus"]
});
We can then place the standard Ember.TextField onto our page without having to create another view to extend Ember.TextField:
{{view Ember.TextField autofocus="autofocus"}}
See JSFiddle: http://jsfiddle.net/MdzhN/
Consider extending Ember.TextField as follows:
App.FocusedTextField = Em.TextField.extend({
didInsertElement: function() {
this.$().focus();
}
});
Then change you handlebars template to use it instead:
<script type="text/x-handlebars">
{{#if isActive}}
{{view App.FocusedTextField}}
{{else}}
<p {{action foo}}> Click Here to Enter text </p>
{{/if}}
</script>

Categories

Resources