Accessing other templates' instances - meteor

You can access the current template's instance by doing Template.instance(). But you often run into situations where you have to access other templates' instances as well. For example, if you use ReactiveVar, then you would want to get or set variables that are attached to other template instances.
I came across How to get the parent template instance (of the current template) but this is not complete.
Q1. How can we access any template's instance, not just the current template's
Q2. Is it against the Meteor way if I need to access other templates' instances?

you can try to set your template variable directly at the template level instead of inside the instance.
Template.example.myVariable = new ReactiveVar();
instead of
Template.example.onCreated(function (){
this.myVariable = new ReactiveVar();
});

The closest I got was to target the template by one of its elements (assume the template contains a form)
Blaze.getView($('form')[0]).templateInstance().someReactiveVar.set('changed')

If your target templates are in the same file, you can just define the reactive variable outside the template functions, at the beginning of the file. All templates in the file will access it.
If your target template is the parent template, (or any further parent template) you can access its data context using Template.parentData() the argument being the rank of the parent (default is 1). It seems that you know that already.
If you need to access a DOM element within a different template in the same page, you can use jQuery selectors.
I don't know any other way to reach another template instance (afaik, there is no Blaze.getTemplate(name) function.) The answer you are referring to seems to be the better you can get.

I think this is purely subjective, since in Meteor there are so many different ways of doing things, but I actually think Session is perfectly suited for sharing variables across several templates. People argue that Session is bad since it's global and can pollute the namespace. I would argue that it's up to the developer to keep their environment clean in any way that works for them. So for instance, this is bad:
Session.set('count', 23);
Session.set('last', new Date());
But this is better:
Session.set('notifications/count', 23);
Session.set('notificatinos/last', new Date());

Related

How to get from JavaScript to TypeScript in ASP.Net MVC?

For obvious reasons we want to start with TS instead of JS in our project.
The problem we occurred are the variables who are set in the MVC Views which are set by the Model of the given View.
E.g. tes.cshtml:
#model Testmodel
<script>
var test = {};
var test.myProp = #Model.Testproperty;
<script>
Now in my test.ts I got an error when I try to get the test-variable because my TypeScript file doesn't know it.
Do I have a architecture miss-conception here? Or is there a trick to do that?
To be honest we have around 100 variables set and / or created in RazorViews, most likely a lot of Ressource-Variables from our resx files we would need e.g. in a java-script alert!
You can create definitions file and put all your global declarations there. For example:
declare interface SampleInterface{
myProp:string;
myFunc(someParameter:string):void;
}
declare var test:SampleInterface;
declare var someFunc: () => number;
More info on writing declaration files here.
One way is to attach to Window all your variables or even all your resource variables and after that you can create something like a helper in typescript where you can parse Window.Variables and Window.ResxVariables for your need.
Server-side you will need two dictionaries Variables and ResxVariables which can be statics in your base controller.
Then you will need two methods that will facilitate adding variables to these dictionaries
Variables.Add("Timezone", "GMT+2");
And
ResxVariables.Add("ExitAlert", "Please stay more");
These two methods will be accessible in your controller actions and you will have the possibility to add model properties too.
Then you will need a HtmlHelper that will help you render those dictionaries as objects attached to Window.
You will need to also support clearing those dictionaries when you render a new page or depends on your need.
When i used something like this, we had two dictionaries GlobalVariables and PageVariables. Global wasn't cleared when we render a new page, but PageVariables was.

Meteor: Call template helper from other template

I have two templates and I've defined JavaScript helpers and events to go with each. When a button is clicked in template A, one of the things I want to do is call a helper function for template B which will change what's displayed on the screen. Is this possible?
If it's not possible, I'd instead like to reload template B.
How can I do either of these? Do I use Tracker.autorun? Reactive variables? Ideally I would do, inside an event function for template A,
B.helpers.call("helperFunctionFromTemplateB");
There are a lot of solutions to what I think you want to achieve, but the answer really depends on context.
If template A is a child template of B:
You can pass a reference to a ReactiveVar in the parent template down to the child template's data context and modify it using {{>childTemplate reactiveVar=reactiveVar}} where reactiveVar is a helper in the parent template that returns the reference to the reactive variable
If the thing you want to change is in the parent's data context, you can use Template.parentData(n) where nis the amount of levels you want to jump up. While modifying the parent's data may not immediately seem reactive, you can make the data prop reactive by accessing it via Template.currentData()
Use some kind of globally accessible state. The most common answer would probably be to use the Session package and use Session.get('var') and Session.set('var', val).
Use an event emitter. This approach gets +'s for decoupling and reusability, but it's also potentially heavy handed if you only need to modify this variable in one place from one source (i.e. your requirements are simple)
Meteor 1.3 - If you want to make references to your reactive data in multiple places but don't want to create a global like Session, use a ReactiveVar or Reactive Dict (closer to session), create your variable where it makes sense, export it, and import it in your templates/anywhere else to be used.
There's a lot of other solutions, these are just the first that come to mind. If you provide more specific context, I'll provide a code sample of what I think's best and explain why. :)

Get data from the parent scope

Im trying to implement a single-page app with Ractive using components, and I need to have some page-wide options. I did like this:
...
data: {
options: {
someOption: true
},
...
Everything was fine while I used it like {{#if options.someOption}}, but then I faced a problem - rective.get('options.someOption') returns undefined (both with ractive.get('options')). Observing dont work as well. Is there any way to make my code understand me?
UPD. Accidentally solved problem with a portion of magic - get() starts working when I place {{options.someOption}} on template.
Ractive programmatic data access within an instance (includes components) can currently only "see" data that is:
Defined as data
Specified explicitly as a component parameter
Used as a reference in the template
For #1, you can include the options as default data and it will be available to all instances:
Ractive.default.data = {
options: {...}
}
Any new Ractive instance, including components, will have an options data property.
For #2, even if you have deeply nested components, you can have the parent of the component that needs the data include it as a parameter:
// Component somewhere in the "app" hierarchy.
// By referencing {{options}} in its template, it will find that data
// make it explicit on the widget component, which can then use it
// programmatically
<widget options='{{options}}'/>
For #3, you can include a "dummy" reference in the component template:
// by using it in the template, it is now available for programatic access
{{#with options}}{{/with}}
Of course then there's #4, enhancing Ractive to allow same lookup in code as template

Conditions in Alfresco policies binding

I have OnCreateNodePolicy implementation and I'm thinking about adding conditions in binding initialization (some optimalizations for speed), is it possible?
What do I mean? Let's have definition similar to this:
policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
ContentModel.TYPE_CONTENT, onCreateNode);
Now when node is created, mine onCreateNode() is called. First thing I do is to check, if my parent has some aspect. Isn't it possible to add this condition into binding definition? So onCreateNode() is called only when this condition is met?
You can not add conditions to the binding definition but in your case you could consider using the OnCreateChildAssociationPolicy instead of the OnCreateNodePolicy. The advantage is that you could bind it to your custom aspect. It would look something like this:
policyComponent.bindAssociationBehaviour(
NodeServicePolicies.OnCreateChildAssociationPolicy.QNAME,
YourCustomModel.ASPECT_YOURASPECT,
ContentModel.ASSOC_CONTAINS,
new JavaBehaviour(this, "onCreateChildAssociation", NotificationFrequency.TRANSACTION_COMMIT)
);
You have to keep in mind though that child associations are also created when you move a node to a new folder, not only when you create it. Also you now have to check the type of the child node (ContentModel.TYPE_CONTENT) in your Java code.

Getting handles to dynamically-generated Flex components

I have a Flex application which references a separate MXML file as a template for a custom component. I create instances of the component dynamically several times in my program, but I need to get a handle that will allow me to modify that instance of the component as desired.
I pass specific information to this component on instantiation using bindable public variables in the component's MXML file. I add it to my main program using addChild().
I want to update the component's progressbar as necessary and I want to remove it from the box to which I addChild'd it.
What's the easiest/best way to get a variable that will give me predictable access to each component so I can easily manipulate the components as necessary? Some research suggests creationComplete, but I decided it was faster to just ask than to go through lots of different experiments and come up blank.
Thanks for all the help. : )
Can you not just keep a list of your components in an array? Presumably you have an object reference when you create them and call addChild() on their parent. Why not just put them in an array at the same time?
var list_of_controls:Array = new Array();
var new_Object:<yourType>;
new_Object = new <yourType>();
parent.addChild(new_Object);
list_of_controls.push(new_Object);
then you can get at them...
var my_Object:<yourType>;
for each (my_Object in list_of_controls)
{
// do something
}
You would have to make sure you dispose of them properly when you re done because the reference in your array would keep them in existence until cleared.
If you decide that you want to use getChildren() instead - which you could - take the time to read the documentation because I think it returns a new array with each call.
I hope that helps.

Resources