Limit reactivity scope to sub-document in Meteor - meteor

I have a mongo document structure as follows:
Gallery
--- Sub-Gallery
------ Image
------ Image
------ Image
--- Sub-Gallery
------ Image
------ Image
.
.
.
Gallery
.
.
.
I would like to represent it on screen. The naive implementation would be:
<name template="gallery">
{{#with get_specific_gallery_helper))
{{#each sub_gallery}}
This is a gallery {{name_sub_gallery}}
{{#each image}}
Something {{name_image}}
{{/each}}
{{/each}}
{{/with}}
The problem with this implantation is that every time a single image data changes the entire Gallery template is re-rendered.
Is there a better way to do it?
Is it possible to limit the scope in every step?
I would like to keep the db structure as is (no normalizing).
Why do I consider it a problem?
First of all it simply does't make sense. Being more practical, I have specific event handlers that are invoked whenever a Gallery/Sub-Gallery/Image are rendered (e.g. fade in the images when loaded). Rendering everything all the time makes it much harder to handle these actions.

Consider reactivity isolation:
<template name="gallery">
{{#each sub_gallery}}
{{#isolate}}
This is a gallery {{name_sub_gallery}}
{{#each image}}
{{#isolate}}
Something {{name_image}}
{{/isolate}}
{{/each}}
{{/isolate}}
{{/each}}
</template>
This localizes changes in the isolate blocks to their own sort of planet so everything around them remains the same and untouched and it still remains reactive
You might have to test it with your document structure though, because each documents index may change when you update it if you store subitems with arrays instead of associative arrays with keys

Related

How to create recursive hbs code in ember?

I have a hbs file that contains following
//some ohter code
-------------------------------------
{{#each items}}
<li>
{{name}}
{{#if items}}
<ul>
//partial should go here
</ul>
{{/if}}
</li>
{{/each}}
---------------------------------------------------
And I want to use same section recursively replacing //partial should go here. How can I do that? Appreciate any help
Ember used to have parital, render and include template tags, which they are trying to get rid of however.
Now, probably the best way is to make use of components. If you are on ember-cli, just open your terminal and type ember g component my-include. It generates a *.js and a *.hbs file (naming depending on whether you are using pods or not).
Then you put the template code you want to use multiple times in the newly created *.hbs file, and then in your existing template code:
{{#if items}}
<ul>
{{my-include}}
</ul>
{{/if}}
You might want to take a look at: https://guides.emberjs.com/v2.9.0/components/defining-a-component/ for more information
You can also look at this sample working twiddle.

Change some html in layout template when on a certain route (with iron-router and meteor.js)

I have a template I have set up as my layout using iron-router:
Router.configure({
layoutTemplate: 'main'
});
Within this layout, I have a line of html that I would like to be changed on certain routes.
My ideas is doing something like:
{{#if landing }}
<div id="page-wrapper">
{{/if}}
However, how do I implement this for a certain route? I want this variable to be true on every route except for 1.
I think that this kind of "change the template based upon what route I'm on" logic fits best into the use of a template for that route (and any others that will make this same change. Depending on the change required, you may be able to call in your base Template into the modified template.
Example:
Router.route('/yourSpecialRoute', function(){
this.layout('OtherLayout');
});
See the Layout docs - I borrowed the syntax of Setting Region Data Contexts
Having said, if you prefer not to switch layouts per route, consider setting a data on your route (something like {data: item} as shown here in the iron:route readme which can then be read by a global helper (Template.registerHelper syntax) - this will at least make it consistent across your routes / templates.

How to use assemble to add a directory of markdown files to my index

I'm trying to add static site generation to a site in order to make it more organised and easier to contribute to. The index file has a section with with an unordered list and a number of list items that all share the same formatting. I would like to dynamically load these list items from a folder of markdown files.
I'm trying to do something like
{{forEach file in the folder}}
<li>
<div class="container">
<div class="display">
{{markdown content of the file}}
</div>
<div class="code">
<pre>
<code class="language-javascript">
{{ string from YFM in markdown file }}
</code>
</pre>
</div>
</div>
</li>
{{/forEach}}
I don't actually want each markdown file to be assembled into it's own page in my dist folder, just used as a dynamic collection of partials for my index file.
Is this possible?
These two parts of an apparently never finished tutorial explain how to use markdown files as a dynamic collection of partials to integrate on the index site:
http://www.andismith.com/blog/2014/02/getting-started-with-assemble/
http://www.andismith.com/blog/2014/02/creating-a-list-of-posts-in-assemble/
Inside the loop that's iterating the md files I used this construct to get the yfm-stripped content "included" as content on the index site (took me quite a while to figure out):
{{#markdown}}
{{page}}
{{/markdown}}
Also refer to the documentation on Collections on http://assemble.io, but careful, there's some conflicting information out there as to the options hash for collections (name: posts vs. name: post, that is, singular vs. plural and autoinflection vs. inflection: post, but bottom line: stick with the variant in the links above :))

Meteor's iron:router isn't doing {{renderRouter}} as expected or documented

I've got a very simple template problem going on that appears to be similar to this guy's problem, though I've tried to build a simple example to demonstrate the problem and hopefully have someone explain to me how to fix or work around it.
Although as I'm doing some online research, it may be that the official documentation is out of date with the code. The reason I haven't bought into accepting that just yet is that the problem seems to have existed for a while, the dates on such articles in forums appears to be fairly old, and there's talk of it being fixed. There's also talk the feature is gone. What's the new way, if there is one?
I'm using Meteor 0.9.0.1 with iron:router 0.9.1. Specifically, I set up my project like this:
$ meteor create ironTest
$ cd ironTest
$ meteor add iron:router
$ meteor
Pointing my browser at http://localhost:3000/ as instructed, shows the default project. So far so good.
Now make ironTest.html contain this:
<body>
<h1>Before</h1>
{{renderRouter}}
<h2>Afterward</h2>
</body>
<template name="hello">
Hello Template
</template>
<template name="goodbye">
Goodbye Template
</template>
Make ironTest.js contain this:
Router.configure({
autoRender: true // we will experiment with this Boolean shortly
});
Router.map(function () {
this.route('hello');
this.route('goodbye');
});
If you go to the routes http://localhost:3000/hello and http://localhost:3000/goodbye, you'll see the templates correctly render as expected and documented, appended to the <body> element, so it appears after the <h2> element.
According to the current documentation for iron:router, one should be able to set the autoRender property to false, and the template should no longer be appended to the <body> element, but rather be injected where the Handlebars (okay, Spacebars) element {{renderRouter}} is, that is, between the <h1> and <h2> elements.
When I try this, visually it doesn't do anything. Opening a JavaScript Console to look at errors shows none. Although, by deliberately going to an invalid route it will show a missing template router exception, showing the routing code is indeed working.
Does anyone know how to coerce the code above into working?
For the curious, I've got a working simplistic equivalent that might be of use to others working this problem.
This new ironTest.html uses a template (for a layout) with no <body>:
<template name="main">
<h1>Before</h1>
{{> yield}}
<h2>Afterward</h2>
</template>
<template name="hello">
Hello Template
</template>
<template name="goodbye">
Goodbye Template
</template>
This ironTest.js instead uses a layout:
Router.configure({
layoutTemplate : 'main'
});
Router.map(function () {
this.route('hello');
this.route('goodbye');
});
It's worth an aside that this solution doesn't work for me, as I don't want a global layout, and have concern that riddling layouts in the route themselves is a tighter coupling than desired for my purposes.
I'm currently looking for a way to dump debugging log information from the Router as it performs transitions, but that's another story.

Meteor - Understanding template 'rendered' calls

I'm a bit of a newb in Meteor so this is possibly a trivial question for you Meteor masters out there.
I use a template which has a couple of child templates:
<template name="parent">
{{> child1}}
{{> child2}}
</template>
I noticed that parent.rendered and child1.rendered functions are invoked when reactive data under child2 changes.
My understanding of meteor docs is that only child2.rendered should be called. So, what I am seeing should not happen, yet for a reason which is beyond me, it does.
To rule out any noise, I gutted the child1 template (to contain only an empty div). Still, its rendered function is called.
Can anyone provide insight?
As of Meteor 0.7.0.1, the parent template will be re-rendered but the sibling child templates will not.
Here is a simple example Meteor app that shows this in action:
https://github.com/alanning/meteor-subtemplate-isolate-test
Keep in mind that Meteor UI is getting a drastic overhaul before Meteor 1.0 lands so a lot of things may change with respect to how templating works.
Just hypothesizing here, but I think the entire page rerenders when any reactive data changes. For example, if you were to have data in Session.get('test') and the only time the value of that is inserted into the DOM is in child2, I believe the entire page still rerenders.

Resources