regularjs / regular

regularjs: a living template engine that helps us to create data-driven component.
http://regularjs.github.io/
MIT License
1.06k stars 149 forks source link

accessing DOM elements generated by regular #20

Closed mekto closed 9 years ago

mekto commented 9 years ago

I'm looking for a way to access DOM elements generated by regular. I haven't found it in the documentation and the source code. But I think it is sometimes neccessery, especially when creating subcomponents using d3 or similar library.

Just by replacing

combine.node(this);

in Regular constructor with

this.$el = combine.node(this);

allows my to access DOM elements, e.g.:

this.$el.querySelector('svg.chart');

which is what I need.

I know that the regular instance has parentNode, but my components somethimes share same parent, so the selector above could select a node from different component.

Another point is that combine.node can return an array instead of an Element. This is what I really like in Regular, that it's components do not need to have a container. For example my component can generate two paragraphs and they can be injected after another two paragraphs and they all share the same parent. In this case this.$el will be an array of Elements, not one single Element. I think it is fine, because you are in control of what your template looks like and know if it at the top level returns one element or an array. Of cource this property could be named like $elements or $nodes and always return an array, not depending on a template.

One thing I haven't found solution yet, is when and how to update the $el property when the top level nodes change. In template

<p>One</p>
{{#if showSecond}}
<p>Two</p>
{{/if}}

the $el property will be an element or an array depending on the value of showSecond variable on init. If the value changes, the $el won't be updated, which is wrong. I think it is a corner case, but it still needs a solution. Please note, that I this condition would be inside one of these paragraphs, not at the top level, the $el wouldn't need any update at all.

leeluolee commented 9 years ago

valuable suggestion. In fact, there have been a way to access the generated dom now —— the ref attribute. either in component or in basic element. This feature is very similar with React 

For example, the template string in Component.

<input ref=basic />
<custom ref=component></custom>

then,

component = new Component();
// the $refs object holds the all reference
component.$refs.basic // ===the  input node
component.$refs.component // === the custom component

This solution may also resolve your question about stuff in statement if. if the test is evaluated to true . the ref will be exsit . if not, the ref will be undefined.

The feature haven't been updated in guide now.

regularjs have been heavily used in production for 2 month now (more than 10 frontend engineers in this project) and I also receive many suggestion, the biggest one is " change the default OPEN and END tag to { and }" which I post in the https://github.com/regularjs/regular/issues/16 . Do you have any suggestion with the issues? I have done the work but doesn't publish now

mekto commented 9 years ago

I didn't know about these $refs. It seems it will work for my needs, thanks.

It is good to know that Regular is used in production. At the beginning I was hasitating if the library is mature enough to use it, but after playing with it I decided to go with it. My project is still at developement stage, but I have already written lots of Regular components for the project and everything works as expected. Previously I have used Ractive.js for several months, but now I am migrating my projects to Regular.js, because in my opinion is just better designed. So expect from me posting suggestions and bug reports if I find any :)

About the opening and ending tag I have no strong opinion at the moment, sorry. But I think you are free to change it to single brackets, it will make templates look cleaner. In fact, I am mixing Jinja templates with Regular templates. To make them work together I changed the tags for Jinja from {{ }} to ${ }. After your change I could leave the defaults.