Reputation: 348
My question is very similar to this one and that one but not exactly the same.
I have the following template in my Meteor application:
<template name="items">
<div class="mainframe">
<h3>Available items:</h3>
<div class="items-table-container">
<table class="table table-hover">
<tbody>
{{#each all_items}}
{{> item}}
{{/each}}
</tbody>
</table>
</div>
</div>
<div class="btn-group">
<button id="create" class="btn">Create new item</button>
</div>
</template>
The template function is trivial:
Template.items.all_items = function () {
return Items.find({}, {sort: {name: 1}}).fetch();
}
There is also an event bound to the #create
button which inserts a new item into the Items collection and that works fine.
Now the most important part is the CSS:
.items-table-container {
height:340px;
overflow-y: scroll;
}
So basically I want my table to have scrollable content inside a fixed size area. The problem start when I scroll down the contents of the items table in one browser and then in another browser I add a new item. The first browser updates the list of items and scrolls the contents back to the top position.
The question is how can I prevent auto update for a single template? I think in this particular case I actually need something like the traditional web page update: that's Ok if a user doesn't see a newly added item immediately but rather after he reloads the page.
Another idea is to do some kind of pagination instead of the scrollable content. I think that would solve the problem however this would be much more complicated and I would like to avoid that.
I think ideally I would like to be able to tell Meteor that I want Meteor to update the template not when the model changes but rather by a request.
Upvotes: 3
Views: 2457
Reputation: 4297
You could also have jquery handle fixing the scroll position. My use-case was having something inserted above the current scroll point in the main body document scrolled text lower.
Not sure yet how to get meteor to run a callback every time a publish set is updated, but you should get the idea:
before = document.body.scrollHeight
// insert your elements
after = document.body.scrollHeight
if $(document).scrollTop() != 0
# scroll us equal to the amount of scroll height added
window.scrollTo(0, $(document).scrollTop()+(after-before) )
Upvotes: -1
Reputation: 832
Isolate the array iteration.
{{#isolate}}
{{#each all_items}}
{{> item}}
{{/each}}
{{/isolate}}
Upvotes: 3
Reputation: 75955
Put your list of items in another template inside the scrollable div container:
<template name="items">
<div class="mainframe">
<h3>Available items:</h3>
<div class="items-table-container">
<table class="table table-hover">
<tbody>
{{> myitems}}
</tbody>
</table>
</div>
</div>
<div class="btn-group">
<button id="create" class="btn">Create new item</button>
</div>
</template>
<template name="myitems">
{{#each all_items}}
{{> item}}
{{/each}}
</template>
Javascript:
Template.myitems.all_items = function () {
return Items.find({}, {sort: {name: 1}}).fetch();
}
//Template.items.all_items = function () {
// remove this helper
//}
This way you can keep the reactivity without putting in a request to update it. Only the portion inside the scrollable box is re-rendered, keeping the position the scrollable container was scrolled to.
Edit: To preserve/freeze your content you could use the preserve function, it takes a css selector as input. e.g
Template.items.preserve(['.items-table-container']);
Upvotes: 4
Reputation: 39
To make a whole region constant so that it doesn't rerender, you can use the block helper {{#constant}}.
If you have specific DOM elements to preserve you can use Template.myTemplate.preserve() which takes as arguments the selectors of the nodes to preserve.
Upvotes: 1