I have this Template:
<template name="body">
{{#if key}}
{{> mite}}
{{else}}
{{> settings}}
{{/if}}
</template>
and
<template name="settings">
<h1>The settings</h1>
<form class="form-inline">
<input id='apiKey' type='text' name='apiKey' placeholder='your API-Key'>
<button id='saveSettings' type='submit' class='btn'>save</button>
</form>
</template>
<template name="mite">
<div>
<h3>...here with key</h3>
<p>
<a id="optout" href="#">not your key?</a>
</p>
</div>
</template>
When I show the settings-form where the user can set the key needed to show the 'mite' template. Now when i 'submit' the form the page get reloaded and the 'mite' template is shown.
On the mite template I'd like to have that link 'not your key?' or something that deletes the key and then shows the settings-form again. It works with a reload... but can't I do this without all the reloading in Meteor? How can i 'call' the template part with the #if in the body template?
-- Renato
You need to bind an event handler to your form and use preventDefault() to stop it submitting. e.g
client side js
Template.settings.events({
'submit':function(event,template) {
event.preventDefault();
var apiKey = template.find('input[name=apiKey]').value;
//..rest of logic to handle submit event
Session.set("key",true);
}
});
You can then use a template helper with Session.get("showthistemplate") to decide whether to show another template or not: (this is a universal helper since you're putting it in and not a template:
Handlebars.registerHelper('key',function() {
return Session.set("key",true);
});
Related
I have a helper for a 'userLayout' template, in which I've defined a current user function. It works fine when I navigate to the template (i'm using flow router with subscriptions in the route). However, when I press 'back' in the browser, the helper fires again.
Why is the helper firing for the template I'm leaving when I press 'back'?
My code for one of the offending helpers is here - I suspect the 'context' attribute:
// Return a specific user
findUser: function(context) {
var id = context.user;
return Potential_users.find({_id: id});
}
EDIT
The view template itself looks like this:
<template name="userLayoutView">
{{#each findUser context}}
...
{{/each}}
</template>
And that view is getting called dynamically like so:
<template name="userLayout">
<div class="row">
<div class="col-xs-12">
{{#if currentUser context}}
{{> userLayoutEditCreate context=context}}
{{else}}
{{> userLayoutView context=context}}
{{/if}}
</div>
</div>
</template>
Template.onRendered :
Callbacks added with this method are called once when an instance of Template.myTemplate is rendered into DOM nodes and put into the document for the first time.
Is there any way to call something after the DOM changed?
For example, a navbar(header) with login/logout button is rendered after user open the homepage, and the navbar is changed after the user logged in(logout button).
I need to do something after the navbar has been changed.
You can refactor your code by creating new templates to introduce finer grained lifecycle events on child templates.
HTML
<template name="navbar">
<div class="navbar">
{{#if currentUser}}
{{> logoutButton}}
{{else}}
{{> loginButton}}
{{/if}}
</div>
</template>
<template name="loginButton">
<button class="login">Login</button>
</template>
<template name="logoutButton">
<button class="logout">Logout</button>
</template>
JS
Template.loginButton.onRendered(function(){
// will print Login after user logged out
console.log(this.$("button").text());
});
Template.logoutButton.onRendered(function(){
// will print Logout after user logged in
console.log(this.$("button").text());
});
Alternatively, you can use an autorun inside Template.navbar.onRendered to listen to user login/logout and perform actions after DOM has been modified using Tracker.afterFlush.
HTML
<template name="navbar">
<div class="navbar">
{{#if currentUser}}
<button class="logout">Logout</button>
{{else}}
<button class="login">Login</button>
{{/if}}
</div>
</template>
JS
Template.navbar.onRendered(function(){
// declare a new reactive computation
// (rerun when the reactive data source is modified)
this.autorun(function(){
// listen to the same reactive data source as in the template helper
// => currentUser
var user=Meteor.user();
// this code will run after every other reactive computations depending
// on the same data source being modified
Tracker.afterFlush(function(){
// will print Logout after user logged in
// will print Login after user logged out
console.log(this.$("button").text());
}.bind(this));
}.bind(this));
});
Code For LoginRegister.html
1.Main Page
2.All the templates are working fine.I think there is no issue regarding the html file
3.Problem is in the router.js file
<!--Home Template !-->
<template name="home">
{{> login}}
</template>
<!--Layout Template !-->
<template name="layout">
<header>
{{> topheader }}
</header>
{{> yield}}
</template>
<!--TopHeader Template !-->
<template name="topheader">
<h1>Welcome</h1>
</template>
<!--Login Template !-->
<template name="login">
<form class="form-horizontal">
<button type="submit" class="btn btn-default signin" id="signInBtn ">Sign in</button>
<button type="submit" class="btn btn-default signup" id="signUpBtn ">Sign Up</button>
</form>
</template>
<!--SignUP Template !-->
<template name="signup">
<h1>SIGNUP <small>Page</small></h1>
</template>
Router.js
This works correctly , When SignUp button is clicked , it flashes sigup template but again reloads home template with login page
Router.configure({
layoutTemplate: 'layout'
});
Router.map(function()
{
this.route('home',{path: '/'});
this.route('signup',{path: '/signup'});
})
loginRegister.js
Java Script File containing events for Both Button Click
if (Meteor.isClient) {
Template.login.events({
'click .signin': function(evt,tmpl){
alert("Sign in button is clicked");
console.log("Registration Form submitted.");
},
'click .signup':function(evt,tmpl)
{
Router.go('signup', {name: '/signup'});
}
});
}
Please help I am stuck and I am new to Meteor so unable to figure it out , and search does not generated good result
You need to prevent your button from submitting, so try something like this in your signup event handler code:
'click .signup':function(evt,tmpl)
{
evt.preventDefault(); // add this to prevent the button from submitting
Router.go('signup', {name: '/signup'});
}
I'm trying to avoid repetitive template code for forms that are essential the same when creating or editing new items.
For example, something like this:
<template name="createOrEdit">
<form role="form">
<div class="form-group">
<input type="text" class="form-control" id="title" placeholder="Title"/ value="{{title}}">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</template>
<template name="create">
{{> createOrEdit}}
</template>
<template name="edit">
{{> createOrEdit}}
</template>
Then, I could created separate template handlers:
Template.create.events(...
Template.edit.events(...
However, those parent template wrappers won't get the events for the main child template.
Is there a way to do what I want?
Those parent templates can get the events from child template. Use it like this:
Template.create.events({
'click .btn':function(){
}
})
Template.edit.events({
'click .btn':function(){
}
})
In Template.createOrEdit.events object you keep events used by both templates and in Template.edit.events and Template.create.events specific code for each.
see proof and
source code
This approach is really nice as you can customize form by passing some variables:
{{# create btnText="create" }}{{/create}}
{{# edit btnText="update" }}{{/edit}}
And in createOrEdit template you can use variable btnText to change button's label.
i would like to trigger the visibility of a block in my handlebars template from an onclick function. i can use sessions and a helper function to get this to work but it seems overkill.
<template name="eventlist">
{{#each eventcollection}}
<div class="eventcontent">
name: {{name}} <br>
{{#if showdetail}}
detail: {{detail}}
{{/if}}
</div>
{{/each}}
</template>
could it be possible to make it work somehow like this?
Template.eventlist.events = {
'click .eventcontent': function() { this.showdetail = true}
}
meteor would just need to check if any attribute of this changed after the event completed and then rerender the template
Why bother Meteor? Such things were easy to achieve in the ancient Javascript days:
<template name="eventList">
{{#each eventCollection}}
<div class="eventContent">
name ...
<span class="eventHidden" style="display: none;">
detail ...
</span>
</div>
{{/each}}
</template>
Template.eventList.events({
'click .eventContent': function(e) {
$(e.target).find('.eventHidden').toggle();
},
});