peerlibrary / meteor-blaze-components

Reusable components for Blaze
http://components.meteorapp.com/
BSD 3-Clause "New" or "Revised" License
354 stars 26 forks source link

Could I check view is ready (after onRendered)? #107

Closed thearabbit closed 8 years ago

thearabbit commented 8 years ago

Could I check view is ready (after onRendered)? Because I have problem with init any Jquery Lib such as datePicker.... on update form (auto form)

Template.myTmpl.onRendered(function(){
   $('[......]')........ // config init
})

It work for insert form, but don't work for update form (auto form)

mitar commented 8 years ago

What do you mean that a view is ready? Define "ready".

thearabbit commented 8 years ago

I want to init any jquery after template rendered. For example I tried to init dateTimePicker

Template.myTmpl.onRendered(
  $('jquery..').dateTimePicker(...........);
)

Don't work, and then I try open the browser console and config init again it work fine.

mitar commented 8 years ago

Template.myTmpl.onRendered is not Blaze Components code.

Also, you should not be using global $ selector, but an Blaze Components instance one.

thearabbit commented 8 years ago

Could example for me.

thearabbit commented 8 years ago

Sorry for my example


class home extends BlazeComponent {
    viewReady() {
                var $exDate = $('[name="exDate"]');
                $exDate.datetimepicker({
                    format: 'DD-MM-YYYY'
                });
    }
}

home.register('home');
mitar commented 8 years ago

You should never use $, but this.$, which binds jQuery only to the component:

class home extends BlazeComponent {
    onRendered() {
                var $exDate = this.$('[name="exDate"]');
                $exDate.datetimepicker({
                    format: 'DD-MM-YYYY'
                });
    }
}

home.register('home');
thearabbit commented 8 years ago

Thanks for your reply, I use auto form but sometime it don't work to binds jQuery like this. And then I tried to open the browser console and config again, it work fine. I think that sometime the view is't yet ready. Now I can't solve this.

nicooprat commented 8 years ago

I guess "ready" means "the DOM has been updated" here. The only trick I found is to use setTimeout:

onRendered() {
                var $exDate = this.$('[name="exDate"]');
                Meteor.setTimeout(function() {
                    $exDate.datetimepicker({
                        format: 'DD-MM-YYYY'
                    });
                },1);
    } 

Hope it helps someone else in the future ;)

mitar commented 8 years ago

What, this is not needed? DOM has been updated just before onRendered is called. When onRendered gets called DOM has just been updated. You do not need that. Moreover, if you need something a small delay, Tracker.afterFlush is probably better than Meteor.setTimeout.

nicooprat commented 8 years ago

Hmm if I add a debugger; in onRendered(), the inspector shows that the DOM hasn't been updated yet. I guess Meteor devs meant that the Blaze component itself has been rendered, but not inserted yet in the global document. But I'm not an expert...

Tracker.afterFlush works too, but I was wondering if it's safe to pass a function to this global object? Meteor.defer() would be possible too.

mitar commented 8 years ago

Hmm if I add a debugger; in onRendered(), the inspector shows that the DOM hasn't been updated yet.

No, the DOM is available, but it might be a DOM fragment. It might not be included yet into the page (because parent DOM elements have not yet been rendered), but you can already manipulate that fragment.

This is a difference between doing $('[name="exDate"]') (searching global page DOM and it might not be there) and this.$('[name="exDate"]') (searches current DOM fragment and it will always be there).

If you want to assure to do something after DOM finished updating as a whole, you should use Tracker.afterFlush.

if it's safe to pass a function to this global object?

What global object? Why not? This is just an API which is exposed like that.