Semantic-ui:css dropdown does not work onRendered

Well that was painful but i think i have a decentish way. A lot of people, I think, have gotten in trouble with semantic-ui and the way it needs you to initialize components in such a way that the onRendered(() => {}) just doesnt do anything. For example, for any template “userProfile” that has a ‘.ui.selection.dropdown.firstName’ element that got rendered in a template inclusion (code further down):

Template.userProfile.onRendered(function () {
$(’.ui.selection.dropdown.firstName’).dropdown();
});

Gets called, but does NOTHING.

The userProfile template looks like this:

<template name=“userProfile”>

{{#if Template.subscriptionsReady}} {{> optionsCombo options=(optionsFor "firstName") }} {{/if}}
`<`/template>

Where optionsCombo is a sub-component (as per the guide for Meteor 1.2), where your actual ‘.ui.selection.dropdown.firstName’ element(s) get rendered in its own template.

I moved the call $(’.ui.selection.dropdown.firstName’).dropdown(); to the onRendered of the subcomponent. It gets called fine, but it doesnt do anything… so well, unto the solution. I hacked this way, it works:

Smart Component blaze:

<template name=“userProfile”>
<div class=“ui form userprofile”>
{{#if Template.subscriptionsReady}}

    {{> optionsCombo options=(optionsFor "firstName") }}
    {{activateSemanticsFor "firstName"}}
     {{> optionsCombo options=(optionsFor "lastName")}}
     {{activateSemanticsFor "lastName"}}
 {{/if}}
`

Smart component javascript:

Template.userProfile.helpers({
optionsFor: function (profileFieldName) {
// getsOptionsForFirstName

  const instance=Template.instance();
  const ret=[];
  return {
  	fieldName: profileFieldName,
  	optionsReady: instance.subscriptionsReady(),
  	optionList:this.profileOptions(profileFieldName)
  };

}
,
activateSemanticsFor: function (fieldName) {
$(’.ui.selection.dropdown.’+fieldName).dropdown();
}
});

And you can see how this hack could somehow be generalized for sub-component types and kind-of get the ensuing disaster under control.

Anyhow, thought Id share and save some pain.

Why are you using the semantic-ui:css package instead of the standard semantic:ui package? I don’t think things like dropdowns will work with the css package.

Well i thought it would be the fastest way to go about this. And last year I was tinkering around and things worked just fine.

Sorry i meant semantic:ui-css . Ill try it the other way then… see if that works.

Nope. It does the exact same thing… :frowning: . I can call $(’.ui.selection.dropdown’).dropdown() from the browser console and it does what it should, but if I put it in an onrendered, it gets called, but does nothing.

When your template gets rendered (and onRendered fires) your optionsCombo has not been loaded, because you told your template to wait for the subscription to be ready. Maybe you should attach your onRendered to optionsCombo.

The usual reason is the options are not fully rendered with data when you call .dropdown() init.

Two solutions:

  1. You may try hook the .dropdown() init to onReady event of template level data subscription.
  2. If you have other calculation intensive to build the option list, put the .dropdown() init into setTimeout. I set it to 300ms for some of my cases, it shall be barely noticeable to users, works okay so far.
1 Like

Thanks for your reply. I did move it to the optionsCombo and it doesnt work either. The problem I think is that it takes some (longer than right when onRendered happens) time for semantics’s dropdown() to be able to do its magic. Im just trying to get a working, mantainable pattern because this form does a lot of things.

Thanks. Ill try the onReady way.

Thank you daveel. You are absolutely right. setTimeout is the best possible strategy. It works perfectly.

You da man. This has been most enlightening.

1 Like

Glad that helped. Yes, there’s still a gap after onReady of subscription before you could call the .dropdown() init. I am still hoping to find some event that tells when a sub DOM has finished rendering with data. No luck so far.