So, Basically i'm new to meteor(0.8.2) and trying to create a basic app having two templates(addnewPlace and Map) and a single button. What i need to get is that, when i click on "Add new Place" button, template "addNewPlace" should be loaded in body or else template "Map" should be loaded. Help will be appreciated :)
My html code:
<body>
{{> menu}}
{{> body}}
</body>
<template name="body">
{{#if isTrue}}
{{> addnewPlace}}// tested this template individually, it works.
{{else}}
{{> maps}} // tested this template individually, it works too.
{{/if}}
</template>
<template name="menu">
<h1>Bank Innovation Map</h1>
<input type="button" value="Add new Place">
</template>
My js code:
Template.body.isTrue = true;
Template.menu.events({
'click input': function(){
//load a new template
console.log("You pressed the addNewplace button");//this fn is called properly
Template.body.isTrue = true;
}
});
Well first of all you obviously aren't changing anything in the click event (true before, true after). But also if you did, I think you might be better off using a session variable for this, to maintain reactivity.
Session.setDefault('showAddNewPlace', false)
Template.body.isTrue = function() { Session.get('showAddNewPlace'); }
Template.menu.events({
'click input': function(){
//load a new template
console.log("You pressed the addNewplace button");//this fn is called properly
Session.set('showAddNewPlace', true)
}
});
Meteor 0.8.2 comes in with the dynamic template include feature. Just set a session variable value on click event and you would like to use the template name on the event.
Session.setDefault('myTemplate', 'DefaultTemplateName');
"click input": function (event) {
Session.set("myTemplate", 'template_name');
}
You can now write this:
<body>
{{> menu}}
{{> body}}
</body>
<template name="body">
{{> UI.dynamic template=myTemplate}}
</template>
<template name="menu">
<h1>Bank Innovation Map</h1>
<input type="button" value="Add new Place">
</template>
You may like to take a look at this article for the reference:
https://www.discovermeteor.com/blog/blaze-dynamic-template-includes/
Related
This is my meteor template:
{{#each p}}
<div class="cpl">
<div class="chat-post">
<li class="post">
<div class="nm" id={{_id}}>
<a>{{username}}</a>
</div>
<div class="con">{{content}}</div>
<div class="cnm">
<div class="t">{{time}}</div>
<div class="m" id="cm">
<a>message </a>
</div>
</div>
</li>
</div></div>
{{/each}}
//TEMPLATE FOR PF
<template name="pf">
<form id="post-box">
<textarea id="new" required></textarea>
<button type="submit">Post</button>
</form>
</template>
//THIS IS MY HELPERS AND EVENT HANDLERS FOR PF AND PC,COLLECTION NAME ROST
Template.pc.helpers({
p: function(){
return Rost.find({}, {sort:{created:-1}});
}
});
Template.pf.events({
'submit form': function(event){
event.preventDefault();
var content= document.getElementById('new').value;
var date= new Date(),
h=(date.getHours()<10?'0':'') +date.getHours(),
m=(date.getMinutes()<10?'0':'')+date.getMinutes();
var time=h+':'+m;
var username= Meteor.user().username;
Rost.insert({
content: content,
created:date,
time:time,
username: username
});
event.target.reset();
}
});
I am using meteor and mongo as DB where {{username}}, {{content}} and {{time}} are variables of object.
How can I access {{username}} using JavaScript?
Inside your helper function, you should already have access to this data via the this context variable, or Template.instance().data. Your event handler should look like:
'click cssSelector'(event,instance) {
event.preventDefault();
}
As you can see, the second parameter is the template instance, so you have access to the data with instance.data, or you use event.currentTarget to determine the element that was click on and go from there. Please post your helpers or event handling code so that we can see what you are trying do and having problem with.
I'm trying to open or close a modal on the click of a button.
My current template looks like this:
<template name="Nav">
{{#if currentUser}}
<button class="settings_toggle">
{{email}}
</button>
{{#if settingsMode}}
<div class="settings_modal">
Your Menus
Sign Out
</div>
{{/if}}
{{else}}
<button class="log_in_toggle">
Sign In
</button>
{{#if loginMode}}
<div class="loginModal">
{{> atForm}}
</div>
{{/if}}
{{/if}}
</template>
And in a corresponding .js file I've set up the necessary helpers and events:
Template.Nav.onRendered(function(){
Session.set('settingsMode',true);
Session.set('loginMode',true);
});
Template.Nav.helpers({
loginMode(){
return Session.get('loginMode');
},
settingsMode(){
return Session.get('settingsMode');
}
});
Template.Nav.events({
'click .settings_toggle'(event){
Session.set('!settingsMode');
},
'click .log_in_toggle'(event){
Session.set(!'loginMode');
}
});
Template.Nav.events({
'click .settings_toggle'(event){
Session.set('!settingsMode');
},
'click .log_in_toggle'(event){
Session.set(!'loginMode');
}
});
Now, I assume this is because of my limited knowledge of javascript, but how would I properly get it to work so that when .log_in_toggle is clicked, it sets loginMode to false if true and vice versa.
Since you have jQuery, you can easily show/hide elements on click events. I don't see a reason to have sessions here.
Events:
'click .settings_toggle': function(){
//Shows a hidden element
$('.elementClass').show()
}
'click .close_modal': function(){
//Hides element
$('.elementClass').hide()
}
In your CSS, have both of the modals have display: none; as the jQuery .show() will make them visible.
In your helpers, and .onRendered(), just erase the sessions because you already display the right elements by checking {{#if currentUser}} and your modals will be initially hidden with CSS and you'll show them with click event.
EDIT
Additionally, you have two Template.Nav.events({}). You can't do that.
The user can only delete a post if he was the one who posted it.However a user can see all the posts.The javascript code is:
var postedBy = Meteor.user();
var currentPost = this._id;
Posts.insert({
name:postName,
createdAt:new Date(),
postId:currentPost,
postedBy:postedBy
});
The HTML code is:
<template name="posts">
{{#if currentUser}}
{{> addPost}}
<ul>
{{#each post}}
<li>{{> postItem}}</li>
{{/each}}
</ul>
{{/if}}
</template>
<template name="postItem">
<li>
<h4>{{name}}</h4>
<i>Posted by {{postedBy.username}} on {{createdAt}}</i>
[Delete]
</li>
</template>
<template name='addPost'>
<input type='text' placeholder='Add post here' name='postName' id ='myinput'>
<button class="btn btn" type="button" id='btn'>Post</button>
</template>
Both currentUser.username and postedBy.username are displaying the names of the logged in user and the user who posted a particular post respectively.
I am trying to work with the Delete anchor tag.
{{#if currentUser.username==postedBy.username}}
[Delete]
{{/if}}
But it shows error in command prompt.I know it is wrong but I can't think of any other way.How do i write this 'if' statement to check if the current user was the one who posted this post?
Please help as I am new to Meteor.Sorry for bad English.
You can't use arbitrary JavaScript expressions in spacebars. Add a helper like this:
Template.postItem.helpers({
canDelete: function (){
return Meteor.user().username === this.postedBy.username;
}
});
Which you can then use in your template like this:
{{#if canDelete}}
Delete
{{/if}}
Also note, instead of copying the user object into each post, the recommended way is to store the user's id in postedBy.
I'm building an app with two views: home & view list
When the user clicks on a list's name on the home view, it should change to the "view list" template. I've added a session variable called 'view', setting it to 'home' on startup. When a click event is detected on one of the items (list name) on the home screen, it changes the value of view to 'viewList'. Then in the HTML, I have an if statement to show the home template if 'view' is 'home', otherwise show the 'viewList' template.
I can tell the first part works because I'm outputting the value of 'view' and it does output the value "viewList" when you click on a list name, it just doesn't change the template.
What am I missing?
My code:
mylists.js:
Lists = new Mongo.Collection("lists");
if (Meteor.isClient) {
Meteor.startup( function() {
Session.set("view", "home");
});
Template.main.helpers({
view: function () {
return Session.get("view");
}
});
Template.home.helpers({
lists: function () {
return Lists.find({}, {sort: {lastUsed: -1}});
}
});
Template.home.events({
"submit #new-list": function (event) {
var name = event.target.listName.value;
Lists.insert ({
name: name,
createdAt: new Date(),
lastUsed: new Date()
});
},
"click .list-row": function (event) {
Session.set("view", "viewList");
}
});
}
mylists.html:
<head>
<title>My Lists</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
{{view}}
{{#if view "home"}}
{{> home}}
{{else}}
{{> viewList}}
{{/if}}
</template>
<template name="home">
<header>
<h2>My Lists</h2>
</header>
<ul id="lists">
<li>
<form id="new-list">
<input type="text" name="listName" value="My List 1">
<input type="submit" value="Save">
</form>
</li>
{{#each lists}}
{{> list}}
{{/each}}
</ul>
</template>
<template name="viewList">
<header>
<h2>View List</h2>
</header>
<!-- list details will show here -->
</template>
<template name="list">
<li class="list-row" id="{{_id}}">{{name}}</li>
</template>
If you want to change from templates view i suggest you tu install the iron:router package.
run
meteor add iron:router
lester create the routes.js on the /lib folder
now lets do this step by step.
First create 1 template on myAppName/client/views/layout.html
<template name="layout">
{{> yield}}
</template>
and update the routes.js with this code.
Router.configure({
layoutTemplate: 'layout' // here we say that layout template will be our main layout
});
Now on the same routes.js create this 2 routes.
Router.route('/home', function () {
this.render('home');
});
Router.route('/viewList', function () {
this.render('viewList');
});
With this if you navigate to localhost:3000/home or /viewList you will see the html content on there.
NOTES: <header> inside the templates you don't need it.
Now this is just an example because i don't really know whats your main idea here.
you are calling {{#each lists}} inside the home template, so whats the point of having the viewList template?
Now if you want to create individual and dynamic routes for each list you can try this.
Router.map(function () {
this.route('listViews', {
path: '/listViews/:_id',
waitOn: function(){
return Meteor.subscribe('lists')
},
data: function(){
return Lists.findOne({_id: this.params._id});
}
});
});
Now with this, you have dynamic templates for each object on the List collection, if you go to localhost:300/listView/35dwq358ew for example you will get render the listView with some data.
you can do stuff like this inside the template list
<template name="list">
<li class="list-row" id="{{_id}}">{{name}}</li>
<li>Check this List in detail</li>
</template>
and the viewList template will look like this.
<template name="viewList">
<h2>{{title}}</h2>
<!-- list details will show here -->
{{informationAboutList}}
</template>
I'm new to ember I am trying to append a template to another and it seems to work but it raises an error, can you please explain why?
The error:
Assertion failed: You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead
This is the code in app.js
App.NewStickie = Ember.View.extend({
click: function(evt){
var stickie = Ember.View.create({
templateName: 'stickie',
content: 'write your notes here'
});
stickie.appendTo('#stickies');
}
});
These are the contents of index.html
<script type="text/x-handlebars">
{{#view App.NewStickie}}
<button type="button" class="btn btn-success">
New
</button>
{{/view}}
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
<div id="stickies">
{{#each item in model}}
<div class="stickie" contenteditable="true">
{{#view App.DeleteStickie}}
<span class="glyphicon glyphicon-trash"></span>
{{/view}}
<div contenteditable="true">
{{item.content}}
</div>
</div>
{{/each}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="stickie">
<div class="stickie">
{{#view App.DeleteStickie}}
<span class="glyphicon glyphicon-trash"></span>
{{/view}}
<div contenteditable="true">
{{view.content}}
</div>
</div>
</script>
Each view in ember have a template, for example:
foo_view.js
App.FooView = Ember.View.extend({
templateName: 'foo'
})
foo template
<script type="text/x-handlebars" data-template-name="index">
<div id=myFooView>Foo</div>
</script>
You are trying to insert a view inside of other in that way:
App.BarView.create().appendTo('#myFooView')
This isn't allowed. You can use the {{view}} handlebars helper to render a view inside other like that:
foo template
<script type="text/x-handlebars" data-template-name="index">
<div id=myFooView>
Foo
{{view App.BarView}}
</div>
</script>
But I think that you want this working dynamically. So you can use the ContainerView, like described by the error message:
App.StickiesView = Ember.ContainerView.extend({
click: function() {
var stickie = Ember.View.create({
templateName: 'stickie',
content: 'write your notes here'
});
this.pushObject(stickie);
}
})
I see in your code a lot of views with the click event, ember encourage you to use actions, this give more flexibility, error/loading handling etc. I think is a good idea to use it.
I hope it helps
You should probably read this guide that explains that ContainerView is. Also, I don't think it's necessary to create another View to append a template to another template.