If child template defined something in onCreated,
Template.test.onCreated(function() {
this.xxx = 'test';
});
And I want to access child context in parent. How can I do that?
You can use Session or ReactiveVar for this operation. But if you need to save it on the child template I think you could use:
var childView = Blaze.getView(currentTemplate.find('#your-child-theme-id'));
and then get template instance by:
var childTemplateInstance = childView._templateInstance;
and then
var myXXXvar = childTemplateInstance.xxx;
But this is a little bit dirty :/ I don't think there is a Meteor API for this particular use case. I think you should play with reactive vars or client only collections etc. I don't know exactly what you want to achieve.
Related
I know the way that lookup DOM with jquery.
Template.foo.events({
'click #bar'(eve, instance) {
$('selector'); //A common way.
instance.$('selector'); // Better performance.
document.querySelector('selector'); // its good too
instance.querySelector('selector'); // its not work
}
})
I know that instance is not node type, so naturally instance.querySelector('selector') can't work!
But I want to use like instance.$('selector').
Is there a way?
instance.find('selector') --> querySelector
instance.findAll('selector') --> querySelectorAll
Note that these both use jQuery under the hood.
If you really want a true browser queryselector without a wrapper use:
instance.firstNode.querySelector('selector')
I have a somewhat weird question.
In Ractive we can do something like this.
App’s template:
<h1>My app</h1><SubComponent/>
And generally have SubComponent’s template access data from App.
Is there any way to have the same behaviour without mentioning SubComponent in the template?
Something like:
const App = new Ractive({el: ‘#myapp’, …………});
const SubComponent = Ractive.extend({ append: true, ………… });
const example = new SubComponent()
example.render(App.el)
But, with example’s template being able to access App’s data, maybe also giving App the chance to find it by using App.findComponent().
What I’m trying to do, is having unpredictable (= I can’t include them inside templates by default) nested components.
Hopefully this makes sense.
Any idea on how to do it?
I don't know if this will work out for you..
But you can just put a div with a known ID in
<h1>My app</h1><div id="subcomp" />
Then mount your dynamic SubComponent under there.
You can use can event like oncomplete - which will guarentee than div#subcomp has been added to dom.
oncomplete: function() {
this.mycompRef = new SubComponent( { el: '#subcomp' });
// You can skip findComponent and use mycompRef
}
I've come across this situation several times now and I realise I'm not really confident about the 'meteor/right' way to handle it.
Suppose I have a form with several parts - each represented by a template - and within each part there are more templates representing eg. datepickers etc.
<template name='myForm'>
{{>partOne}}
{{>partTwo}}
<button class='submit'>Submit</button>
</template>
<template name='partOne'>
{{>widget}}
{{>widget}}
</template>
<template name='widget'>
<input class='datepicker' />
</template>
I want to keep track of my form as the user fills it out - on the level of the 'myForm' template - but all the events are happening at the level of 'widget'.
One solution I keep seeing (e.g. in this SO answer) is to just put everything in the global Session variable. Like so
Template.widget.events({
'click .select' : function(event, template){
var name = template.data.name;
Session.set(name, $(event.currentTarget).val());
}
});
And then in myForm I should do something like this
Template.myForm.rendered = function(){
Tracker.autorun(function(){
var name = Session.get('name');
// do something
});
}
But as my forms are getting more complicated, I find this is really turning into a mess on the myForm template level, all while filling up my Session variable with data that isn't really application-global.
I'd be really grateful for any ideas on how others deal with this ! Keeping templates and widgets modular while still being able to follow and react to their triggered events from parent templates...
You're not alone in feeling like something just isn't right. This is one of the reasons there's a lot of talk about a Blaze 2. Here's what I do:
Create an app global namespace (e.g. G = {}). I usually use the first letter of the app name & do this in lib/config/_namespace.js
Put your collections in G.Collections or G.C,
Put your shared functions in G.Fx, etc...
Put your template vars in G.T.
Then, save that variable to G.T.varName. In doing so, you can use it in rendered as well as events and helpers. As a perk, it's super easy to find all your "globals" because they're all in the G object. Additionally, you can now 'use strict' again.
Then, to keep it clean:
Template.parentTemplate.destroyed = function() {
G.T = {};
};
So if you need reactivity, just make a ReactiveDict:
Template.parentTemplate.created = function() {
G.T.RD = new ReactiveDict();
};
You can use a file-level ReactiveVar or ReactiveDict, instead of the Session object.
I have a template with few elements (input, radioButton etc). If I want to access to these DOM elements within mytemplate I can either access them within events
Template.myForm.events({
'click #submitButton' : function (event, template) {
//template variable here gives me access to the
//current template instance, so I can get to any
//DOM element within this template.
}
})
OR within
Template.myForm.rendered = function () {
//within this function I have access to "this" which points to template instance
}
I was wondering if there is a way to access the DOM Elements that a declared within a template outside of these event functions and rendered callback?
Thanks in advance
You can but you need to reference the template instance.
The reason for this is a single template can be used multiple times. In this case a single easy to use way to access the template would not know which instance it would belong to. This is why you need to use a reference, such as done in the example below.
You have to store the instance somewhere when it is rendered:
TheTemplateInstance = null;
Template.myForm.rendered = function() {
TheTemplateInstance = this;
}
Then you can use TheTemplateInstance anywhere you want, provided the template is on the DOM.
If you use myForm many times then it will only have access to the one created last.
Also You did not give a use case for your intentions. But there are several better ways to do most things with a template:
JQuery modding something when some variable changes (the most common use case where helpers aren't useful)
Template.myForm.rendered = function() {
var self = this;
this.autorun(function() {
var xx = something.findOne();
self.$("something").autoform() //Some jquery call
});
}
and helpers:
Template.myForm.helpers({
someName: function() {
return Session.get("name");
}
});
You can then use {{someName}} in your template's html where it can change when you use Session.set("name", "a new value");
I have this parent node with text and I want to add a media into the parent node also if the text is changed will update as well.
{
parent: {
text: 'this is content'
}
}
The media value from a third-party callback. How to pass it to update()? I tried {media: callbackVal} but not working.
$scope.parent = angularFireCollection(firebaseRef.child('parent'));
$scope.parent.update(What_to_do_here, function(error){
//something...
});
UPDATE
Maybe my question is not clear enough.
In Firebase JS, we can do this to update or insert media into the node.
new Firebase(firebaseRef).update({ media: 'value'} );
How to do this in `angularFireCollection ?
Check out the annotated AngularFire source: http://angularfire.com/src/angularFire.html#section-38
It looks like AngularFireCollection.update() takes a key/item and a callback function. So you need to edit the entry you want to update directly in your AngularFireCollection, (e.g. $scope.parent.getByName('media').value = 'alligator scrimshaw') and then call $scope.parent.update($scope.parent.getByName('media'), function(err) { ... }).
NOTE: One rather confusing thing (which maybe I am misunderstanding) is that there doesn't seem to be a way to add data to an AngularFireCollection by id. So if media doesn't already exist in your Firebase, $scope.parent.getByName('media') will return undefined. For this reason, if you don't need explicit syncing, and implicit syncing is fine, I would use an AngularFire object instead of an AngularFireCollection.