Using Meteor sessions to toggle templates - javascript

I'm brand new to JavaScript and Meteor, and am a little stuck in trying to create edit functionality for a list item to be able to modify properties of the list item (from a Mongo document). I can make it work if I make editMode a boolean property of the item itself, but I'd like it to be local and temporary rather than stored with the document itself.
Looking at the code below, you'll notice I'm still green and don't yet completely understand what I'm doing, but you should be able to understand what I'm trying to do :)
The code is somewhat there, but am trying to hook up changes in the session, based on toggling an edit button, to get the edit mode template to render. Here's what I have (stripped down to the relevant stuff):
// Item template
<template name="item">
<div class="item">
<span>{{itemText}}</span>
<span class="glyphicon glyphicon-pencil item-edit" aria-hidden="true"></span>
</div>
<div class="mod-table">
{{#if this.editMode}}
{{> modTable}}
{{/if}}
</div>
</template>
// Associated .js file
Session.set(this.editMode, false);
Template.item.events({
'click .item-edit': function() {
if (this.editMode) {
Session.set(this.editMode, false);
} else {
Session.set(this.editMode, true);
}
}
});

Don't use Session variables because they are global thus considered bad practice, you should use a ReactiveVar tied to your item template instead.
item.html :
<template name="item">
<div class="item">
<span>{{itemText}}</span>
<span class="glyphicon glyphicon-pencil item-edit" aria-hidden="true"></span>
</div>
<div class="mod-table">
{{#if editMode}}
{{> modTable}}
{{/if}}
</div>
</template>
item.js :
Template.item.created=function(){
this.editMode=new ReactiveVar(false);
};
Template.item.helpers({
editMode:function(){
return Template.instance().editMode.get();
}
});
Template.item.events({
'click .item-edit': function(event,template) {
var editMode=template.editMode.get();
template.editMode.set(!editMode);
}
});
Don't forget to meteor add reactive-var to your project !

Related

Meteor show / hide element on button click

I have a template like so:
<template name="Menus">
<button class="btn_create new_menu_toggle"><i class="fa fa-plus"></i> Create a new menu</button>
<button class="btn_cancel new_menu_toggle"><i class="fa fa-times"></i> Cancel</button>
{{> NewMenu}}
</template>
What I'm trying to accomplish is that initially only the btn_create is shown. If .btn_create is pressed, the {{> NewMenu}} is rendered and the .btn_create is replaced with btn_deny. Vice versa for the behaviour of btn_deny.
How would I go about doing this in Meteor I know I could probably accomplish this by adding / changing classes in vanilla Javascript, but I'd like to know if there's an easier method using Meteor / Blaze.
A simple pattern is to use a session variable to track the state
html:
<template name="Menus">
{{#if createMode}}
<button class="btn_create new_menu_toggle"><i class="fa fa-plus"></i> Create a new menu</button>
{{> NewMenu}}
{{else}}
<button class="btn_cancel new_menu_toggle"><i class="fa fa-times"></i> Cancel</button>
{{/if}}
</template>
In your javascript you need to set up some event handlers to toggle the state:
Template.Menus.events({
'click .btn_create'(ev){
session.set('createMode',true);
},
'click .btn_cancel'(ev){
session.set('createMode',false);
}
});
When the template is rendered you need to initialize the session variable:
Template.Menus.onRendered(function(){
session.set('createMode',true);
});
Finally you need the helper your template can use for the spacebars conditional expression:
Template.Menus.helpers({
createMode(){
return session.get('createMode');
}
});

Use replace function inside Meteor.js Spacebars [duplicate]

I like to work with meteor, but I have a problem I can't find a solution for.
In the template file I have this code:
<template name="klussenboard">
<h2>Klussen</h2>
<div class="klussenboard">
{{#each klus}}
{{#if status=1}}
<li>
<a class="startlink" href="#"><img src="/images/starten.png"></a>
</li>
{{/if}}
{{/each}}
</div>
</template>
This is the js client code
Template.klussenboard.klus = function () {
return Klussen.find({"status": { $gt: 0 }}, {
sort: {datum: -1}
});
};
But this doesn't work. How can I do a statement in a template file?
Looking forward to an answer.
Spacebars (meteor's templating library), much like Handlebars (that it is based on) doesn't execute arbitrary expressions like, say, angular.js's templates.
If you change the statement you're trying to write into a helper method, like so (feel free to pick a better name!):
<template name="klussenboard">
<h2>Klussen</h2>
<div class="klussenboard">
{{#each klus}}
{{#if isEnabled}}
<li>
<a class="startlink" href="#"><img src="/images/starten.png"></a>
</li>
{{/if}}
{{/each}}
</div>
</template>
You could then define the isEnabled helper in any client side .js file - say, client/klussenboard.js like so:
Template.item.isEnabled = function() {
return this.status == 1;
}
So, this, in helper functions is
This assumes that you are in a context where status is a variable (which, based on your question, you are)
This would then reactively update whenever the status variable changes.

Meteor combined with Session.set and jQuery in one call

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.

Emberjs. How to grab clicked related data?

Am new in emberjs and I am trying to copy a practice using solely jquery. I cannot seem to able to do it. Maybe I should approche the following in a different way?
I have a view:
{{#each clip}}
<div class="large-3 columns">
<div {{action panel_clicked uuid}} class="panel" style="overflow:hidden; height:200px;">
{{view Ember.TextField valueBinding="notes" type='hidden'}}
{{view Ember.TextField valueBinding="uuid" type='hidden'}}
{{{chunk}}}
</div>
</div>
{{/each}}
What I want to do is when I click on the class='panel' I get the uuid and use that to get the hidden text fields.
Usually I will just have a custom id for the hidden field such as id='notes_[uuid]' so in jquery I can just do something like $('#notes_' + uuid).val() However I haven't figure out a way to generate a dynamic id in the Ember.TextField.
So is there a way to dynamically generate id in Ember.TextField or I should think bout it differently?
Thanks
You could just pass in the object to the action.
{{#each clip}}
<div {{action panel_clicked this on="click"}} class"panel">
...
</div>
{{/each}}
Where this refers to the current object in the each loop.
Then your action would just take the object as a parameter:
panel_clicked: function(clip) {
alert(clip.get('someAttr')); // just to show it works
... // what you want to do
}
Check out the documentation as well.
Clicking on a view will generate a 'click' event on that view. The event.context will be the model bound to that view.
App.ActionPanelView = Ember.View.extend({
click: function(evt) {
var model = evt.context;
....
}
});
{{#each clip}}
{{view App.ActionPanelView valueBinding=clip}}
{{/each}}
Ember should maintain all the bindings. If you ever find yourself

Ember.js hiding a divider with buttons, but maintaining didInsertElement functionality

I'm trying to show and hide some buttons in Ember.js as follows.
{{#view App.myView contentBinding="App.myObject"}
<div id="my_widget" class="well span3">
{{#if content.isConditionTrue}}
<button id="stop_button" class="btn btn-primary"> Stop </button>
<button id="start_button" class="btn btn-primary" > Start </button>
<button id="record_button" class="btn btn-primary">Record </button>
</div>
{{else}}
<div id="widget_warning_box" class="well">
<p> No cameras are open, open a camera in Add/Remove Cameras tab. </p>
</div>
{{/if}}
</div>
{{/view}}
and the View looks like:
App.myView = Ember.View.Extend({
didInsertElement: function() {
$record = $("#record_button")
$start = $("#start_button")
$stop = $("#stop_button")
$record.click(function(){
console.log("record clicked")
});
$start.click(function(){
console.log("start clicked")
});
});
And the myObject controller is
App.myObject = Ember.Object.create({
isConditionTrue : false;
});
This sort of works (the buttons are replaced by the text if myObject.isConditionTrue is false, and appear when isCondionTrue is true) but when the buttons are displayed, they have no functionality on click. I guess its because they are not in the DOM when didInsertElement is called. So, is there some way to fix this? Should I do child/parent View setup? Any pointers appreciated.
Well I'm definitely not the guy who can tell what's the right way to do this, because I'm just learning ember too, but here is my working approach on fiddle
http://jsfiddle.net/drulia/zkPQt/
Basically every time you switching myObject.isConditionTrue to false, ember removes your buttons from DOM and that's why your jQuery selectors stops working. I attached ember js {{action}} helper and placed functions responding to the events in myObject, now buttons are working and showing action result on the screen.

Categories

Resources