Closed bartonhammond closed 9 years ago
atNavButton
is in your case not a base class, nor a Blaze Component, but just a template. You cannot inherit from template. Templates in Blaze Components are used only for HTML content, events and helpers do not propagate to the component. So inheritance between Blaze Components (if you would be doing it) comes from JavaScript inheritance between classes, not because you are using a template.
The main reason why this is not so is because in Blaze template helpers this
is a data context, while in Blaze Components methods this
is a Blaze Component. So by blindly inheriting template helpers most of them would not work properly anyway.
You could create a function for yourself which takes a template as input, and copies its template helpers to the prototype of your Blaze Component, passing to each of them data context as this
.
I'm confused more now. I am following exactly (imo) the very first example presented at http://components.meteor.com/. Rather then the "input" template/js I am using "atNavButton" template/js. What is different?
Can you show me where is code for 'text' as the base class, namely AT.prototype.
.
BTW, you could do something like:
var WebixNavButton = BlazeComponent.extendComponent({
template: function () {
return 'atNavButton';
},
text: function() {
return Blaze._getTemplateHelper(Template.atNavButton, 'text', Template.instance)();
},
events: function () {
return [{
'click *': this.onClick
}];
},
onClick: function (event) {
console.log('WebixNavButton.onclick');
}
}).register('WebixNavButton');
So the atNavButton.js is
// Simply 'inherites' helpers from AccountsTemplates
Template.atNavButton.helpers(AccountsTemplates.atNavButtonHelpers);
// Simply 'inherites' events from AccountsTemplates
Template.atNavButton.events(AccountsTemplates.atNavButtonEvents);
And AccountsTemplates.js is
// Constructor
AT = function() {
};
AT.prototype.atNavButtonHelpers = {
text: function(){
return 'AT.prototype';
}
};
AT.prototype.atNavButtonEvents = {
'click #at-nav-button': function(event){
event.preventDefault();
console.log('AT.prototype.atNavButtonEvents.click');
},
};
AccountsTemplates = new AT();
Side note - I'm trying to incorporate the ui library http://webix.com with the "useraccounts" package. This code mirrors what I'll encounter when I actually add the "useraccounts:core" package.
As you can see from http://webix-components.meteor.com/ that the atNavButton renders just fine.
Thanks for your help!
Yes. As I said, template helpers are not copied over to the Blaze Component. You created a template atNavButton
and assigned some template helpers to it (including text
). You are then using that template as a Blaze Component template. Blaze Components use template only as content, ignoring events and template helpers. I explained above why (because this
is not scoped correctly).
Ok...this worked (note the function invocation ...)
text: function() {
return Blaze._getTemplateHelper(Template.atNavButton, 'text', Template.instance)();//note ()
},
Is there anyway to have this execute automatically such that if I didn't like that default behavior I'd have to implement my own version of this "text" method? Seems it should work by default since this is class based inheritance .
I'm confused (even more). So in your initial example both the template and the embedded html element is called "input". I assumed you were subclassing the template named 'input' which is the pattern I followed.
On Wed, Sep 16, 2015 at 7:01 PM, Mitar notifications@github.com wrote:
Yes. As I said, template helpers are not copied over to the Blaze Component. You created a template atNavButton and assigned some template helpers to it (including text). You are then using that template as a Blaze Component template. Blaze Components use template only as content, ignoring events and template helpers. I explained above why (because this is not scoped correctly).
— Reply to this email directly or view it on GitHub https://github.com/peerlibrary/meteor-blaze-components/issues/70#issuecomment-140929200 .
No, you are not extending any class here. You are just using a template. Blaze Components do not extend templates. Blaze Components can extend other Blaze Components.
Yea, you could create a mixin which would that for you. Something like:
class ExposeTemplateHelpersMixin extends BlazeComponent
mixinParent: (mixinParent) ->
template = mixinParent.template()
if _.isString template
template = Template[template]
for name of template.__helpers
name = name.substr(1)
mixinParent[name] = Blaze._getTemplateHelper(template, name, Template.instance)
super
Read the text there:
The input template we provided earlier will serve as the markup to be re-used by the component. However, all the helpers and events will be provided through the component class.
Templates do not have any inheritance. They are bunch of HTML + helpers + events. And Blaze Components reuse HTML, but provide their own way of helpers and events (in a different way, a way which can in our opinion has more sense).
So the issue with just copying template helpers over is that you cannot really extend them in a reasonable way. So in OOP way. To extend and call super
. Because they work differently than methods.
So when I read this
The input template we provided earlier will serve as the markup to be re-used by the component. However, all the helpers and events will be provided through the component class.
I thought the helpers were inherited as well as the input template.
I will review your comments and figure out where I'm missing it all...seems I've totally misunderstood.
Please do suggest improvements to the text. :-) I do not know how could However, all the helpers and events will be provided through the component class.
be understood that helpers are coming from the input template?
Ok - thanks for all your help- I need to review all of this again. Thanks.
So yea. Sorry, but blaze templates are inherently made so that it is hard to reuse them. This is why Blaze Components try to approach things from a different perspective so that you can extend things like you are used in OOP. And this means some legacy stuff is hard to deal with in a consistent way.
I think your 'ExposeTemplateHelpersMixin' is what I'm looking for. Not being a CS guy, I need to work through this.
I get it now that the helpers & events are not passed through. My bad.
Not to belabor this, but conceptually, for me, a Blaze template is a Object or Component - it has a View (the template) and the Controller is the combination of the Helpers and Events. I don't quite understand why the Helpers and Events are thrown away in the Blaze Components implementation. Take for example the "text" Helper implementation for the "useraccounts:core":
text: function(){
var key = Meteor.userId() ? AccountsTemplates.texts.navSignOut : AccountsTemplates.texts.navSignIn;
return T9n.get(key, markIfMissing=false);
}
Why would this complex behavior be tossed away just because the "View"/template will be changed/replaced? I can't imagine introducing a new component UI implementation of User Accounts if I have to reimplement all this behavior? Anyway, it's your design and it looks like the mixin you proposed should help.
Thanks for all your help. I think Blaze Components will be a key enabler for the work I'm trying to accomplish.
OK, see another possible implementation of text
as a Blaze templates helper:
text: function () {
return this.username;
}
Now, if we expose this as a method call, we cannot just copy this code over, because in Blaze Components, this
in methods are component instances, not data context. If we wrap it in something, which mingles the data context, maybe. But then it is a bit strange to extend a helper with a method, where this
changes.
Similar for event handlers.
I opened #71.
Thanks very much for the consideration.
Maybe, just an idea, to keep your original vision, you could make available that Mixin capability and see if people actually use it.
For me to continue my research, I'll need it for sure as my focus is changing the view rather then the behavior.
If you could whip that up, I'll test it for you. Otherwise, I'll start writing it now.
I apologize if this is obvious to everyone else...
If my base component displays data, shouldn't my component that inherits from it display the same provided I do nothing to prevent it?
For example, my base template atNavButton is like this:
And my new component WebixNavButton looks like this:
My index.html page is
When running http://webix-components.meteor.com/, I expected to see the WebixNavButton display the same 'text' as the base class, namely AT.prototype.
Is it possible to get access to the value from the base class helper function "text"?