Callback after the DOM was updated in Meteor.js

2020-01-24 04:17发布

I have this Meteor project: https://github.com/jfahrenkrug/code_buddy

It's basically a tool with a big textarea and a pre area that lets you enter source code snippets that automatically get pushed to all connected clients.

I'd like to automatically run the highlightSyntax function when the code was changed, but it doesn't really work.

I've tried query.observe, but that didn't work too well: The syntax highlight flashed up once and then disappeared again.

So my question is: How do I run code after the DOM was updated?

标签: meteor
9条回答
叼着烟拽天下
2楼-- · 2020-01-24 04:29

A hacky way to do it is:

foo.html

<template name="mytemplate">
  <div id="my-magic-div">
    .. stuff goes here ..
    {{add_my_special_behavior}}
  </div>
</template>

foo.js

Template.mytemplate.add_my_special_behavior = function () {
  Meteor.defer(function () {
    // find #my-magic-div in the DOM
    // do stuff to it
  });
  // return nothing
};

The function will get called whenever the template is rendered (or re-rendered), so you can use it as a hook to do whatever special DOM manipulation you want to do. You need to use Meteor.defer (which does the same thing as settimeout(f, 0)) because at the time the template is being rendered, it isn't in the DOM yet.

Keep in mind that you can render a template without inserting it in the DOM! For example, it's totally legal to do this:

console.log(Template.mytemplate())

So when a template is rendered, there is not a 100% guarantee that it is going to end up in the DOM. It's up to the user of the template.

查看更多
▲ chillily
3楼-- · 2020-01-24 04:34

There is no callback after the DOM is updated, however you can force all pending DOM updates with Tracker.flush().

After you call flush(), you know the DOM has been updated and so you can perform any manual DOM changes you need.

查看更多
闹够了就滚
4楼-- · 2020-01-24 04:38

This question is quite old, but the two-year-later solution would be to integrate an operational transformation library with Meteor and use Ace or CodeMirror on the client, which does the syntax highlighting automatically. This has the additional benefit of allowing people to edit at the same time.

I've already done the work for you :)

查看更多
冷血范
5楼-- · 2020-01-24 04:38

It seems Template.myTemplate.rendered doesn't work properly or I don't get it...

I need to load TinyMCE inline after a template with all posts are rendered, so I have :

- a Template

<div id="wrapper">     
         {{#each posts}}
             <div class="editable">{{post}}</div>
         {{/each}}        
  </div>

- and a Function

Template.myPosts.rendered = function(){
      console.dir($("div"));
      tinymce.init({
          selector: "div.editable",
          inline: true,
          plugins: [
              "advlist autolink lists link image charmap print preview anchor",
              "searchreplace visualblocks code fullscreen",
              "insertdatetime media table contextmenu paste"
          ],
          toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});

}

However the console logs only the <div id="wrapper"> and not the <div class="editable"> divs, which contain my posts. So, it seems Template.myTemplate.rendered callback occures before the template is rendered, right?

EDIT: I put the Template.myTemplate.rendered code inside a setTimeout() and all seems to work, so I'm sure Template.myTemplate.rendered causes the problem.

查看更多
萌系小妹纸
6楼-- · 2020-01-24 04:42

Starting with Meteor 0.4.0, Template.myTemplate.rendered provides a callback that

is called once when an instance of Template.myTemplate is rendered into DOM nodes and put into the document for the first time.

More info at http://docs.meteor.com/#template_rendered

查看更多
聊天终结者
7楼-- · 2020-01-24 04:42

In Blaze Components (I am one of authors) you have an API which calls methods when DOM is inserted, moved, or removed. You can see here how to make an reactive variable when DOM changes.

The downside with this approach is that it does not change when DOM element attributes change (like class change). Only when DOM elements themselves are changed. This works for most cases, but if you need the second, I suggest you simply use MutationObserver. In this case you will be able to respond also to outside changes.

查看更多
登录 后发表回答