Session variable resetting between pages - meteor

I'm learning Meteor and I'm trying to use the counter example with Iron Router.
Everything is working in the counter page and the routes too, except that when I'm navigating between pages and come back to the counter page, the counter resets to 0 (after I've clicked and incremented the counter).
The HTML is:
<template name='counter'>
<button>Click Me</button>
<p>You've pressed the button {{counter}} times.</p>
</template>
and the javascript is:
Session.setDefault("counter", 0);
Template.counter.helpers({
counter: function () {
return Session.get("counter");
}
});
Template.counter.events({
'click button': function () {
Session.set("counter", Session.get("counter") + 10);
}
});
I tried to put
Session.setDefault("counter", 0);
inside a template.counter.rendered/template.counter.created but it's the same.
Does anyone knows how to guarantee that session values can be preserved?

It seems that everything is working as expected and it was my problem: as I was trying to test dynamic routes, sometimes I changed the URL manually on the browser instead of using the "go back" button or navigate using my own page links.
And, as it is supposed, by doing that I'm refreshing the page, and everytime I refresh a page I loose session values...
Hope this could be useful to someone else.

Related

How do I get onRendered to run a second time when the route changes but the template remains the same?

I have an iron-router route for updating the data of a specific project:
Router.route('/project/:key/update', {
...
});
Each time the user navigates to an "edit project page" I want to focus the project-name input.
template.onRendered(function() {
this.$('form input[name="project_name"]').focus();
});
This works great when navigating from the Dashboard to any given edit project page. However, navigating to/from one project page to another the onRendered function doesn't rerun and consequently the input is not focused.
You can force onRendered to reevaluate after a context change by adding a check for currentData inside of an autorun like this:
Template.myTemplate.onRendered(function() {
var self = this;
this.autorun(function() {
// hack to force the autorun to reevaluate
Template.currentData();
// insert onRendered code here
self.$('form input[name="project_name"]').focus();
});
});
For more details, see the end of this issue.

VideoJS with Meteor 0.8 Blaze

Previously I used the rendered function to initialize videoJS when the Video Changed.
Now in Meteor 0.8. the rendered is only fired once, when the template was created.
The problem is: the template is used in each page, I navigate through, so it is never rerendered and just changed the attributes.
Is there any way to get VideoJS working in Meteor 0.8?
Something like rendered function for template fields that fires always
or a way to force the complete template to rerender
or a way to run a callback when the content of a helper is inserted.
I have found a solution to force the behaviour of Meteor < 0.8:
Make 2 Handlers:
UI.registerHelper "handler1", (data) ->
Session.set("loading", true);
UI.registerHelper "handler2", (data) ->
if Session.get("loading")
Session.set("loading", false);
return true
else
return false
Define 2 Template:
<template name="videoPlayer">
{{handler1 seed="videourl"}}
{{#if handler2}}
Loading Player...
{{else}}
{{> videoPlayerInternal}}
{{/if}}
</template>
<template name="videoPlayerInternal">
<!-- VideoJS-Player-Code -->
</template>
Now, I can hook the rendered method of videoPlayerInternal and this works like meteor < 0.8.
This works because:
In Initialization, only handler1 is called. This sets the variable "loading" to true.
After that I have a if-then-else that in the initial state shows a loading text. Because the condition is calculated by a helper that has a side effect (setting the session variable loading to false) it will be called immediatly after that.
So If I load another exactly same page with another video url, it needs to re run the handler1, wich sets the session variable to true again, that deletes the template from the dom and reinserts that. The rendered is called again and voila it works ;-)
Oh... and of course, the rendered method:
Template.videoPlayerInternal.rendered = ->
videojs.options.flash.swf = "/video-js.swf"
# Delete old players and reset.
if videojs.players.videoJsPlayer
videojs.players.videoJsPlayer.dispose()
# Initialize the player
$vid_obj = _V_ "videoJsPlayer", {}, ()->
console.log "video is ready.";
return true

Framework7 starter page "pageInit" NOT WORKING

anyone using framework7 to create mobile website? I found it was great and tried to learn it by myself, now I meet this problem, after I create my App, I want to do something on the starter page initialization, here, my starter page is index.html, and I set data-page="index", now I write this below:
$$(document).on('pageInit', function (e) {
var page = e.detail.page;
// in my browser console, no "index page" logged
if (page.name === 'index') {
console.log("index page");
});
// but I changed to any other page other than index, it works
// my browser logged "another page"
if(page.name === 'login') {
console.log('another page');
}
});
Anyone can help? Thank you so much.
I have also encountered with the same problem before.
PageInit event doesn't work for initial page, only for pages that you navigate to, it will only work for index page if you navigate to some other page and then go back to index page.
So I see two options here:
Just not use pageInit event for index page - make its initialization just once (just make sure you put this javascript after all its html is ready, or e.g. use jquery's on document ready event)
Leave index page empty initially and load it dynamically via Framework7's mainView.loadContent method, then pageInit event would work for it (that was a good option for me as I had different index page each time, and I already loaded all other pages dynamically from underscore templates)
I am facing same issue and tried all solutions in various forums.. nothing actually worked. But after lot of RnD i stumbled upon following solution ...
var $$ = Dom7;
$$(document).on('page:init', function (e) {
if(e.detail.page.name === "index"){
//do whatever.. remember "page" is now e.detail.page..
$$(e.detail.page.container).find('#latest').html("my html here..");
}
});
var me = new Framework7({material: true});
var mainview = me.addView('.view-main', {});
.... and whatever else JS here..
this works perfectly..
surprisingly you can use "me" before initializing it..
for using for first page u better use document ready event. and for reloading page event you better use Reinit event.
if jquery has used.
$(document).on('ready', function (e) {
// ... mainView.activePage.name = "index"
});
$(document).on('pageReinit', function (e) {
//... this event occur on reloading anypage.
});

How to add Search with Meteor and Bootstrap?

I am trying to implement searching in my Meteor app. I don't exactly understand how it ties together. At this point, I have this following code:
html:
<form class="navbar-search pull-left">
<input type="text" class="search-query" placeholder="Search">
</form>
js:
Template.menubar.events({
'keyup input.search-query': function (evt) {
console.log("Keyup value: " + evt.which);
if (evt.which === 13) {
console.log("Got an Enter keyup");
Session.set("searchQuery", "justATestVar");
}
}
});
I can see the values of keyup as I press different keys into the search box, so I know the event is being hit. Capturing the "enter" keyup also works, but pressing enter causes the enter site to reload and when I do:
Session.get("searchQuery")
it returns undefined.
I don't know if I'm handling this properly. Essentially, I just want to get the value from the search box and then use that value for making a search on my collection. Any help would be appreciated! Thank you.
You should really use a submit button for your search form to avoid ruining accessibility.
Using a submit button will also enable by default the behavior you're looking for : form submission on enter key pressed.
If you really want to get rid of the submit button, keep it in the DOM but use CSS to hide it.
It's very important to call preventDefault on the event you'll receive from "submit form" handler, if you forget to do so, the page will refresh ruining the meteor "Single Page App" experience (and by the way, page refresh will clear your Session variables, which is why you get an undefined value in the first place).
"submit form":function(event,template){
event.preventDefault();
Session.set("searchQuery",template.find(".search-query").value);
}
What is probably happening is your form is being submitted when you hit enter. Try an preventDefault(). Probably something like this would work:
Template.menubar.events({
'keyup input.search-query': function (evt) {
console.log("Keyup value: " + evt.which);
if (evt.which === 13) {
console.log("Got an Enter keyup");
Session.set("searchQuery", "justATestVar");
}
},
'submit form': function (evt) {
evt.preventDefault();
}
...
You could also try adding evt.preventDefault(); in your keyup but I think it's the form submission that's doing it.
In case anyone got here trying to implement the search function as well, I recommend the following:
meteor add matteodem:easy-search
On client and server:
Players = new Meteor.Collection('players');
// name is the field of the documents to search over
Players.initEasySearch('name');
On the client, make a template.html:
<template name="searchBox">
{{> esInput index="players" placeholder="Search..." }}
<ul>
{{#esEach index="players"}}
<li>Name of the player: {{name}}</li>
{{/esEach}}
</ul>
</template>
Reference

Reactive updates not received in other browsertabs

Meteor promises reactive updates, so that views are auto-updated when data changes. The included leaderboard example demonstrates this. It runs fine when I test it: data is updated across several browsertabs in different browsers, as expected.
All set and go, I started coding with meteor and progress was being made, but when I tested for reactive updates across browertabs, I noticed that only after a short while the updates across tabs stopped.
I boiled down the problem to the following code, based on a new empty meteor project:
updatebug.html
<head>
<title>updatebug</title>
</head>
<body>
{{> form}}
</body>
<template name="form">
<form onsubmit="return false;">
{{#each items}}
{{> form_item }}
{{/each}}
</form>
</template>
<template name="form_item">
<div>
<label>{{name}}
<input type="text" name="{{name}}" value="{{value}}">
</label>
</div>
</template>
updatebug.js:
Items = new Meteor.Collection("items");
if (Meteor.is_client) {
Template.form.items = function () {
return Items.find();
};
Template.form_item.events = {
'blur input': function(e) {
var newValue = $(e.target).val();
console.log('update', this.name, this.value, newValue);
Items.update({_id: this._id}, {$set: {value: newValue}});
},
};
}
if (Meteor.is_server) {
Meteor.startup(function () {
if (Items.find().count() === 0) {
Items.insert({name: 'item1', value: 'something'});
}
});
}
Run in multiple browsertabs, start changing the value of the input in one tab. The other tabs will reflect the change. Goto the next tab and change the value. Repeat a couple of times.
After a while, no more updates are received by any other tabs. It seems that once a tab has changed the value, it does not receive/show any more updates.
Differences compared to the leaderboard example (since it's very similar):
The leaderboard uses no form controls
The leaderboard example does an increment operation on update, not a set
I am about to file a bug report, but want to be sure I am not doing anything stupid here, or missing an essential part of the Meteor Collection mechanics (yes, autopublish package is installed).
The issue here is input element preservation. Meteor will preserve the input state of any form field with an id or name attribute across a template redraw. The redraw is preserving the old text in your form element, because you wouldn't want to interrupt another user typing in the same field. If you remove the name attribute from the text box, each tab will update on blur.
In fact, I'm not sure why the first update works in your example. That may actually be the bug!
You can see it's not a data problem by opening the console in each browser. On each blur event you will get an updated document in every open tab. (Type Items.find().fetch())

Resources