How to reload (re render) template in Meteor - meteor

I am working on a chat app that supports multiple languages. The basics of the app is working fine however I have small problem when changing chat rooms.
Each room is setup to support 2 languages. When sending a chat message you can choose which language you are sending the message in. This is done by clicking on a small icon of a flag which toggles between the 2 flag icons. The template for this is:
<template name="chatBar">
<div id="chatBar" class="input-append input-prepend">
<form id="chatForm">
<span class="add-on"><img src="/images/flags-iso/flat/16/{{chatMessageLang}}.png" id="lang"></span>
<input id="chatMessageLanguage" type="hidden" value="{{chatMessageLang}}">
<input id="chatMessageTarget" type="hidden" value="{{chatMessageTargetLang}}">
<input class="input-xxlarge" id="chatMessage" type="text" placeholder="← choose your language and then type your message here…">
<button class="btn" id="sendNewMessage" type="submit">Send</button>
</form>
</div>
and is called from another template:
<template name="chat">
{{> chatroom}}
<div id="chatWindow">
<ul>
{{#each chats}}
<li class="{{messageClass}} {{_id}}">
<img src="/images/flags-iso/flat/16/{{langOriginal}}.png">
{{langTo.flagicon}}
{{user}}:
<span class="message" lang="{{langOriginal}}">{{original}}</span>
{{#if translated}}
<span class="message" lang="{{langTranslated}}">{{translated}}</span>
{{/if}}
{{#if correction}}
<i class="icon-remove"></i>
<span class="friendCorrection">{{correction}}</span>
{{/if}}
<span class="messageOptions">{{{messageOptions}}}</span>
</li>
{{/each}}
</ul>
</div>
{{> chatBar}}
</template>
The problem I have is when I change chatrooms the language options are being retained from the previous chatroom I was in. The code for setting the languages for the chatbar is:
Template.chatBar.helpers({
chatMessageLang: function() {
//return getCurrentChatroomInfo().langFrom.iso;
return Meteor.user().profile.langNative;
},
chatMessageTargetLang: function() {
var chatroomLang1 = getCurrentChatroomInfo().langFrom.iso;
var chatroomLang2 = getCurrentChatroomInfo().langTo.iso;
if(Meteor.user().profile.langNative == chatroomLang1){
return chatroomLang2;
} else {
return chatroomLang1;
}
}});
function getCurrentChatroomInfo(){
return Chatrooms.findOne({_id : Router.current().params['_id']})
}
How do I make the variable chatMessageTargetLang reactive to the loaded chatroom (each chatroom has their own route).
Thanks
Adam

Related

How to update document of particular user id

Basically what I want to do is, just update user details.so when
I input user ID all the other details of user are displayed in
textbox. Then I can edit anything.
Below is my js code:
Template.body.onCreated(function() {
this.currentTextBox = new ReactiveVar();
});
Template.body.events({
"keyup .new-task1"(event, instance) {
instance.currentTextBox.set(event.target.value);
}
});
Template.body.helpers({
dbs() {
const instance = Template.instance();
return Dbs.find({'user_id':instance.currentTextBox.get()});
}
});
Template.temp.events({
"submit .sub"(event) {
const target= event.target;
const name1 =target.name.value;
const add1 =add.value;
const r1 = target.r.value;
const const1 = target.const.value;
console.log(doc_id1);
Dbs.update({"user_id" : "pid"},{"name" : "name1","r" : "r1","const"
: "const"});
}
});
Now the problem is I am not able to update the edited field, though the value of edited field is sent to js file from html.anyone help me to solve this issue as I am new to meteor and mongo db.
Html code:
<head>
<title>eg1</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
</head>
<body>
<nav class="#e57373 red lighten-2">
<div class="container">
<div class="nav-wrapper">
hello
<ul id="nav-mobile" class="right hide-on-med-and-down">
</ul>
</div>
</div>
</nav>
<div class="row">
<div class="col s2">
<form class="new-task">
<input type="text" name="pid" placeholder="patient_id" class="new-
task1"/>
</form>
</div>
<div class="col s4">
<ul class="collection">
{{#each dbs}}
{{>temp}}
{{/each}}
</ul><br><br>
</div>
</div>
</body>
<template name="temp">
<li class="collection-item">
<form class="sub">
<input type="text" name="user_id" value=" {{user_id}}"/>
<input type="text" name="addd" value=" {{add}}"/>
<input type="text" name="r" value=" {{r}}"/>
<input type="text" name="const" value=" {{const}}"/>
<center><input type="submit" value="Submit" class="waves-effect
#607d8b grey btn"></center>
</form>
</li>
</template>
Welcome to Meteor :)
You have to use $set attribute when you are updating document,
use as below and let me know.
Dbs.update({"user_id" : "pid"},{$set:{"name" : "name1","r" : "r1","const" : "const"}});
For more info on Collection.update Click Here.
Also go through Mongo Update Query example to know how to update a document when you directly use mongo shell.
Remember there are few differences when you directly use Mongo Shell commands and Meteor Collections.

Template helper to wait till user account gets checked

This Meteor client code causes the headerLabel on the page to flicker first to "Please login" then to "Select item from menu" in the case of an existing valid account. How can it be fixed so that it shows no "Please login" since their is a user logged in already? Thanks
edit
As suggested in Ramil's answer. the modified code below still does not work and I still get the flicker of "Please login".
Template.header.helpers({
headerLabel: () => {
const user = Meteor.user();
if (user) {
return user.profile.header || Session.get('header') || 'Select item from menu';
} else {
return 'Please login';
}
}
});
<template name="header">
<header>
<h1 class="main-menu">
<button class="mainMenu" type="button">☰</button>
</h1>
{{#if currentUser}}
<p class="header">
{{headerLabel}}
</p>
{{else}}
<p class="header">
Please login
</p>
{{/if}}
<h1>
<button class="subMenu" type="button">⋮</button>
</h1>
</header>
</template>
There is builtin {{currentUser}} helper in accounts package.
You can use it to check whether the user is logged in.
<template name="header">
<header>
{{#if currentUser}}
<p>
Select item from menu
</p>
{{else}}
<p>
Please login
</p>
{{/if}}
</header>
</template>

Meteor Flow Router issue with update

I have a Meteor app and I'm transitioning from IronRouter to FlowRouter. So far so good, but there are aspects I don't understand yet.
I have a route as follows:
FlowRouter.route('/documents/:docId/edit', {
name: 'documentEdit',
subscriptions: function (params, queryParams) {
this.register('documentEdit', Meteor.subscribe('documentSingle', params.docId));
},
action: function (params, queryParams) {
BlazeLayout.render('layout', { top: 'header', main: 'documentEdit' });
},
});
First option:
Then I also have a template:
<template name="documentEdit">
<div class="container">
<h1>Edit document</h1>
{{#if isReady 'documentEdit'}}
{{#autoForm collection="Documents" doc=this id="documentForm" type="update" meteormethod="documentUpdateMethod"}}
<fieldset>
{{> afQuickField name='title'}}
{{> afQuickField name='content' rows=6}}
</fieldset>
<button type="submit" class="btn btn-primary">Update</button>
<a class="btn btn-link" role="button" href="{{pathFor 'documentsList'}}">Back</a>
{{/autoForm}}
{{/if}}
</div>
</template>
with a template helper as follows:
Template.documentEdit.helpers({
isReady: function(sub) {
if(sub) {
return FlowRouter.subsReady(sub);
} else {
return FlowRouter.subsReady();
}
}
});
This is as it is mentioned here, but I'm not getting the values pre-filled in the textboxes on the UI (which is normal when editing fields).
Second option:
When I do the following it works and I don't really understand why it works (found it browsing in different forums and tried it out):
<template name="documentEdit">
<div class="container">
<h1>Edit document</h1>
{{#with getDocument }}
{{#autoForm collection="Documents" doc=this id="documentForm" type="update" meteormethod="documentUpdateMethod"}}
<fieldset>
{{> afQuickField name='title'}}
{{> afQuickField name='content' rows=6}}
</fieldset>
<button type="submit" class="btn btn-primary">Update</button>
<a class="btn btn-link" role="button" href="{{pathFor 'documentsList'}}">Back</a>
{{/autoForm}}
{{/with}}
</div>
</template>
and the helper:
Template.documentEdit.helpers({
getDocument: function () {
return Documents.findOne();
}
});
So the questions are:
for the 1st option: any idea why it does not work. I would prefer that one as it's the documented way of doing things
for the 2nd option: not sure why I need (in the template helper) to do a Document.findOne() without even having to pass the id of the doc I want to edit:
You want to do template level subscriptions with Flow Router, that's one of the primary pattern changes.
So you'd do:
Setup the subscription at the template level. Autorun so it'll resubscribe on route changes.
Template.documentEdit.onCreated(function() {
var self = this;
this.autorun(function() {
var docId = FlowRouter.getParam('docId');
self.subscribe('documentSingle', docId));
};
};
Setup the template helper to pick up from the route, and grab the id and populate the helper/document.
Template.documentEdit.helpers({
getDocument: function () {
var docId = FlowRouter.getParam('docId');
var doc = Documents.findOne(docId) || {};
return doc;
}
});
Do a template level load check and if it's there render it, otherwise show loading...
<template name="documentEdit">
<div class="container">
<h1>Edit document</h1>
{{#if Template.subscriptionReady}}
{{#with getDocument }}
{{#autoForm collection="Documents" doc=this id="documentForm" type="update" meteormethod="documentUpdateMethod"}}
<fieldset>
{{> afQuickField name='title'}}
{{> afQuickField name='content' rows=6}}
</fieldset>
<button type="submit" class="btn btn-primary">Update</button>
<a class="btn btn-link" role="button" href="{{pathFor 'documentsList'}}">Back</a>
{{/autoForm}}
{{/with}}
{{else}}
Loading...
{{/if}}
</div>
</template>
Not knowing how this worked, seeing that all the tutorials I have read that deals with update used Iron router, I have spent 7 days worth of trying retrying, looking through others code, reading tutorials. Happy it now works.

Meteor accounts-list

I want to display all registered accounts in my meteor app. I published and subscibed to the Meteor.users collection and build a template to show email-addresses. The problem is I don't understand how I should navigate the data.
<template name="contacts">
<br>
<ul class="list-group">
{{#each users}}
<li class="list-group-item">
<span class="badge">14</span>
{{emails}}
</li>
{{/each}}
</ul>
</template>
{{emails}} is an array with json-objects and I don't know how to handle it to get the "address" field displayed.
This is my JS:
Template.kontakte.users = function (){
return Meteor.users.find();
}
First create a subtemplate, looks better:
<template name="contacts">
<ul class="list-group">
{{#each users}}
{{> user}}
{{/each}}
</ul>
</template>
<template name="user">
<li class="list-group-item">
<span class="badge">14</span>
{{email}}
</li>
</template>
In template user the userObject is available via this pointer. The email can be shown with helper functions.
Template.user.helpers({
email: function() {
return this.emails[0].address;
}
});
Note, this just shows the first email in your array.

Getting the outer context of a Meteor Template

I have the following use-case: There are rooms which have beds inside. (Bummer...)
There is a loop of rooms which uses a template "room".
<template name="rooms">
{{#each availableRooms}}
{{> room}}
{{/each}}
</template>
This template gets for each iteration a room. This is accessible by this.
<template name="room">
<div class="room-outer">
<button type="button" class="btn" data-toggle="collapse" data-target="#list-{{_id}}">
{{name}} : {{getBeds this}} beds free.
</button>
<div id="list-{{_id}}" class="collapse in room-inner">
{{#each guests_id}}
<div class="bed">
<div class="blanket">
{{showUser this}}
</div>
</div>
{{/each}}
</div>
</div>
</template>
Now I like to calculate some special value which I do by extending the template. I need now to pass the this variable to the getBeds function. Is it possible to do this by grabing outside the template and get the room into the function?
Template.room.getBeds = function (room) {
if (room.guests_id)
return room.beds - _.size(room.guests_id);
else
return room.beds;
};
Basically I don't want to have to write {{getBeds this}} but only {{getBeds}}
Shouldn't this work?
Template.room.getBeds = function () {
if (this.guests_id)
return this.beds - _.size(this.guests_id);
else
return this.beds;
};
See the docs:
Helpers can take arguments, and they receive the current template data in this:

Resources