ractive : how to call super () inside a child class? - ractivejs

That is going to be a super easy question. I have the following code :
var component = ractive.extend ({
...
onrender : function (){...}
...
})
var view = component.extend({
...
onrender : function (){...}
})
The onrender in view is executed and shadows the onrender in component. Is there a way to call the onrender in component from the view context?

You can use this._super inside the overriding method to refer to the underlying function:
onrender: function(){
this._super();
// ...
}
It's on this page in the docs (though example is with the old lifecycle methods).

Related

Meteor.js: template.<html>.events vs Template.<template>.events 'this' binding seems inconsistent

I'm looking through the Meteor simple tutorial and the way that 'this' binding in the different Template objects works seems inconsistent to me in my unknowledgeable state.
Template.body.events({
"submit .new-task": function(event) {
console.log(this); // Logs an empty object
}
})
Template.task.events({
"click .toggle-checked": function() {
console.log(this); // logs a task
}
});
I can see that task is an xml template defined in the view, which is a visual representation of the items returned by a function in the Template.body.helpers object.
I guess that the task objects are bound the html representation of each object (though I can't see how as there doesn't seem to be any identifying property within the li elements??)
Anyhow. When I click the task, this is the task. But when I submit the form, I was expecting this to be the body. Why is it not?
I was expecting Meteor to handle Template.body and Template.task in a similar way
In Meteor this referes to the data context. You define it with helpers or with the route controller ( IronRouter or FlowRouter)
Example:
{{#with myData}}
<h1>{{title}}</h1>
{{/with}}
js
Template.yourTemplate.helpers({
myData : function(){
return {
title : "My title"
}
}
})
You need to use the "event" argument
Template.task.events({
"click .toggle-checked": function( event , instance ) {
console.log( event );
}
});
The instance argument is also very useful. You have access to a jQuery selector like: instance.$() and it will only search for elements on your template and also child templates.
Personally I use the instance a lot. My Favorite pattern is:
Template.task.onCreated(function(){
this.vars = new ReactiveDict();
this.data = "some data";
});
Later if you want to access vars or data:
Events - You get this on the arguments
Helpers - var instance = Template.instance();
With instance you avoid storing states in the global namespace, like Session, and your code is a lot easier to maintain and understand. I hope this helps you to understand how template works in Blaze.

Accessing iron router data from helper functions

Refer to the code below please:
Router.route('/posts/:_id', function () {
this.render('Post', {
to: 'content',
data: function () {
return Posts.findOne({id: this.params._id});
}
});
});
If a Post object has title and body fileds in MongoDB, I can access them from Post.html template like
<h4>Post title: {{title}}</h4>
<h3>Post body: {{body}}</h4>
I would like to access Post object from Post.js in a template helper function. Is it possible?
Update:
According to this question: Meteor data-context with iron-router, I can access the data variable like this:
Template.Post.rendered = function() {
console.log(this.data)
}
Is there a way to do this inside Template.Post.events ?
Seems like you are looking for the Template.currentData() method.
Template.example.events({
'click #test':function(e,t){
console.log(Template.currentData())
}
})
update Seems like using currentData have differents behaviors depending the case check this
So it seems like if you want to use it, you it should be inside a DOM element.
Template.post.events({
'click h4':function(){
console.log(Template.currentData()) // and should return the title.
}
})
based on the stubalio says.
Inside an event handler, returns the data context of the element that
fired the event.

How can I access DOM Elements declared within a template outside Template.myTemplate.events, Template.myTemplate.rendered etc

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");

Render callback to all templates in meteor blaze

I am forced to assign rendered callbacks to all my templates.
Until 0.9.0 I used to do it like this:
_.each( Template, function( template, name ) {
//...
template.rendered = function() {
//...
};
});
But now, Template is a constructor and not an object, so this method won't work here. Is there any way to pass callback function to all templates or fire function when all templates were rendered using Blaze?
Here is a quick workaround I came up with, iterating over every Template property to find out if it corresponds to a template definition, and if it does, assign the onRendered callback.
// make sure this code is executed after all your templates have been defined
Meteor.startup(function(){
for(var property in Template){
// check if the property is actually a blaze template
if(Blaze.isTemplate(Template[property])){
var template=Template[property];
// assign the template an onRendered callback who simply prints the view name
template.onRendered(function(){
console.log(this.view.name);
});
}
}
});
I don't know what's your use case so there may be better solutions depending on it.
With Meteor 1.2.1 the Template object has an onRendered(hook) function to accomplish an 'all template' onRendered behaviour.
Template.onRendered(function(){
var template = this;
Deps.afterFlush(function() {
console.log("triggering Jquery mobile component creation for "+template.view.name);
$(template.firstNode.parentElement).trigger("create");
});
});
The postponed update via Deps.afterFlush(callback) is optional and subject to your application needs.

Iron-Router RouteController Inheritance: Why does the Parent Controller's Hook run before the Child's?

I've been working with the fantastic Iron-Router package (0.7.1) for Meteor (0.8.1.3) and have run into something that seems somewhat counter-intuitive. I have provided an example below.
The following code was written in context of the Iron-Router's provided Tinytests.
https://github.com/EventedMind/iron-router/blob/devel/test/both/route_controller.js
var Parent = RouteController.extend({
onBeforeAction: function(pause) {
console.log('I\'m in the parent!');
pause();
}
});
var Child = Parent.extend({
onBeforeAction: function(pause) {
console.log('I\'m in the child!');
pause();
}
});
var inst = new Child(Router, route, {});
inst.runHooks('onBeforeAction');
The test resulted in the Child printing out "I'm in the parent"
I had expected for the Child to print out "I'm in the child"
I feel like with Object Oriented Programming, it would be more natural for the Child's onBeforeAction to override the Parent's.
That being said, if that is intentional, how can I subvert the order of the hooks and have only the Child's onBeforeAction run?
It looks like it is intentional:
https://github.com/EventedMind/iron-router/blob/devel/lib/route_controller.js#L97
// concatenate together hook arrays from the inheritance
// heirarchy, starting at the top parent down to the child.
var collectInheritedHooks = function (ctor) {
var hooks = [];
if (ctor.__super__)
hooks = hooks.concat(collectInheritedHooks(ctor.__super__.constructor));
return Utils.hasOwnProperty(ctor.prototype, hookName) ?
hooks.concat(ctor.prototype[hookName]) : hooks;
};
If you don't want the parent hook to run, it looks like you'll have to skip using inheritance and do something like mixin common functionality into the various controllers.

Resources