Cameron
Cameron

Reputation: 2975

Is there a hook in either the controller or router to be called after all DOM elements have been rendered?

Let's say I want to do some jQuery stuff

// Do jQuery Stuff
$(document).ready(function(){
  $("button").click(function(){
    $("p").hide();
  });
});

And I want to include this code in either the route or the controller, I'm quite sure I cannot implement this because there's no hook function (I.E. model(), renderTemplate(), etc. that I can use that guarantees that all the elements in the DOM have safely been rendered.

Now, if I were doing this in a component, I know I could call the didInsertElement hook and that could would allow me to run the code above.

My Use Case

I want to use a library called ScrollMagic which would require jQuery to configure. Someone other than me has already written a lot of code in the route and controller. We could easily just move this to a component (and we probably will), but I still wanted to ask this for my own curiosity.

Question

Is there any hook in either the route or the model that guarantees all the elements of that template have been rendered in the DOM? If not, why is that? After all, you have that hook available in a component.

Upvotes: 0

Views: 45

Answers (1)

NullVoxPopuli
NullVoxPopuli

Reputation: 65183

The route and controller don't have any after render hooks

Generally the way you'd want to accomplish an afterRender thing, is to either use a custom element-modifier (new): https://github.com/emberjs/ember-render-modifiers (or bind an action to did-insert)

Or, you can make a renderless component that just has a didInserElement hook defined.

So, in your template:

<BindButtonsToHideParagraphs />

and then inside that component:

export default class BindButtonsToHideParagraphs extends Component {
  didInsertElement() {
    document).ready(function(){
      $("button").click(function(){
        $("p").hide();
      });
  }
}

though, based on the jQuery you've provided, I highly recommend you use normal actions on the button, and conditional if/elses to show/hide the p tags.

that would look something like this:

<button {{action 'toggleParagraph'}}>click me</button>

{{#if this.showParagraph}}
  <p>text</p>
{{/if}}

export default class SomeComponent extends Component {
  @action
  toggleParagraph() {
    this.set('showParagraph', !this.showParagraph);
  }
}

or, if you are using the sparkles components: https://github.com/rwjblue/sparkles-component

<button {{action this.toggleParagraph}}>click me</button>

{{#if this.showParagraph}}
  <p>text</p>
{{/if}}

export default class SomeComponent extends Component {
  @tracked showParagraph = true;

  toggleParagraph() {
    this.showParagraph = !this.showParagraph;
  }
}

Upvotes: 2

Related Questions