Double material select element (second one fetching content


Topic: Double material select element (second one fetching content from DB) freezes website and browser tab

nextstepmedia pro asked 4 years ago

Hey guys, I've encountered problems with the new Material select. If I select a country in select1 the material select freezes and so does the browser tab. I am fetching conditional data on a country select element. select1 choose country, select2 fetches data onchange like:
$('document').ready(function() {

  // Initialize next, prev & submit button
  initEvents();
  // Populate & link countries and regions
  varcountrySelect=$('#ProfileProfileCountryId');
  varcountryId=countrySelect.val()
  loadRegions('#ProfileProfileProvinceId', countryId);
  countrySelect.change(function(event){
    loadRegions('#ProfileProfileProvinceId', $(this).val());
  });
});

// Load Regions
function loadRegions(selector, countryId) {
  var url = '/users/places/countries.json?data%5BProfile%5D%5Bprofile_country_id%5D=' + countryId;
  $.getJSON(url ,function(resp) {
    var select = $(selector);
    select.material_select('destroy');
    select.empty();
    $.each(resp, function(id, title) { 
      $('<option>').val(id).text(title).appendTo(select); 
    });
    select.material_select();
  });
}

nextstepmedia pro answered 4 years ago

@Sebastian Kaczmarek provided me with the fix:

Please try adding data-stop-refresh="true" to the select element. It should disable the feature connected with that.

See https://mdbootstrap.com/docs/jquery/changelog/#v4-5-9


chrissigler pro premium answered 4 years ago

I experience something very similar when I try to disable options using JS. To illustrate this, go to the Bootstrap Select demo and run the following pair of lines a couple times in your JS console: `$('select option').prop('disabled', true);` `$('select option').prop('disabled', false);` If your experience is similar to mine, you'll see Chrome's memory footprint go crazy when you do this. Initial Footprint: ~130k After Opening Console: ~155k After Disabling: ~165k After Enabling: ~229k After Disabling Again: ~432k After Enabling Again: ~2.5g While it ramps up all this extra memory usage, naturally the CPU for that tab spikes to ~100%, leaving the browser completely unresponsive until the change finishes. This is a couple seconds at the first toggle. At the final toggle, I waited for more than 15 minutes on my i7 with several gb of RAM to spare. I eventually had to leave to take my kids to school. When I returned, it had finally finished. Obviously, it's not a real-world use case to change out 73 select options at the same time. However, I only uncovered this issue last night when trying to change only *two* select options last night. That caused a similar unresponsive state after only two toggles and I had to abandon using disabled states and use error messages instead.

nextstepmedia pro commented 4 years ago

Thanks for the additional info, this behavior is exactly as you described for me too. Hopefully the mdb guys can come up with a fix for this :)

nextstepmedia pro answered 4 years ago

Video to illustrate the bug: https://vimeo.com/287627163  password: 12345 I think the problem resides in the onchange event. This is the cakephp file I use
<div class="genres area">
  <h2><?= __('Waar kom je vandaan?')?></h2>
  <div class="genre-container">
    <div id="#country_province" data-valMsg="<?= __('Kies een land en provincie')?>">
      <div class="genre genre1">
        <?php
          echo $this->Form->input('Profile.profile_country_id', [
            // 'options' => [1 => 'Nederland', 2 => 'België'],
            'label' => false,
            'class' => 'mdb-select initialized',
            'div' => false,
            'aria-required' => 'true',
            'tabindex' => '-1',
            'aria-hidden' => 'true',
            'autocomplete' => 'country-name',
            'aria-describedby' => 'ProfileProfileCountryId-error'
          ]);

          echo $this->Form->input('Profile.profile_province_id', [
            // 'options' => array(0 => '') + $profileProvinces,
            'div' => false,
            'label' => false,
            'class' => 'mdb-select',
            'aria-required' => "true",
            'tabindex' => "-1",
            'aria-hidden' => "true",
            'autocomplete' => 'province-name',
            'aria-describedby' => "ProfileProfileProvinceId-error"
          ]);
        ?>
      </div>
    </div>
  </div>
  <div class="submit-container row">
    <div class="col-12 col-sm-6 mb-1 mb-sm-0">
      <button type="button" class="btn-prev btn btn-block btn-inactive" tabindex="-1"><i class="fa fa-arrow-circle-left mr-1"></i><?= __('Vorige')?></button>
    </div>
    <div class="col-12 col-sm-6">
      <button type="button" class="btn-next btn btn-block btn-success"><?= __('Volgende')?><i class="fa fa-arrow-circle-right ml-1"></i></button>
    </div>
  </div>
</div>

Huichofer pro answered 4 years ago

So, after upgrading my files with version 4.5.10 (that contains the fix Sebatian mentioned), my browser still crahsed after a couple times I updated the target select with dynamic data. But I kept playing with the code and found that if you clean/empty the select BEFORE  destroying it, then it doesn't freeze/crash. If you compare the code in my previous comment the he one below, you'll see that I moved the .empty() call, that did the trick.
$("#ddlLeagues").change(function () {
  $("#ddlTemplates").empty();
  $("#ddlTemplates").material_select("destroy"); 
  var league = $("#ddlLeagues").children("option").filter(":selected").val();
  $.getJSON("/api/leagues/" + league + "/templates")
    .done(function (data) { 
      $("#ddlTemplates").append("<option value='' selected='selected'></option>");
      $.each(data, function (index, item) {
        $("#ddlTemplates").append($("<option>", { value: item.id }).text(item.name));
      });
    });
  $("#ddlTemplates").material_select();
});
If this is correct (so far it fixed my problem) then this should be mentioned in https://mdbootstrap.com/javascript/material-select/#updating-destroying Hope it helps you nextstepmedia.

Piotr Glejzer staff commented 4 years ago

Hi, thanks for your solution. We will check it! Have a nice day. Best, Piotr

nextstepmedia pro commented 4 years ago

Thanks for sharing man! It is functional this way! Still looks a bit buggy though so I will be waiting for an update from MDB so this will work from the getgo.

nextstepmedia pro answered 4 years ago

Is something known about a fix? This issue is dragging on for a while now!

Sebastian Kaczmarek staff pro premium commented 4 years ago

Just to clarify. What bug are you talking about? "Material select freezing browser" or "Only the list in select2 is being updated correctly. The list in select3 is unchanged although I had already changed the list in select3 via Javascript."? Also, which version are you using?


nextstepmedia pro commented 4 years ago

It does not seem resolved in the latest version (4.5.13) if you use more as one select dropdown the page freezes/takes a while to refresh the other fields. The effect gets worse as more options are loaded. 

Right now my project is stuck because I cannot update my project (2 months ago) as this bug was introduced a version after that.
I test with the newest version of MDB ofcourse.

The JS I use:

$('document').ready(function() {
// Initialize next, prev & submit button
initEvents();

 

// Populate & link countries and regions
varcountrySelect=$('#ProfileProfileCountryId');
varcountryId=countrySelect.val()

 

loadRegions('#ProfileProfileProvinceId', countryId);

 

countrySelect.change(function(event){

 

loadRegions('#ProfileProfileProvinceId', $(this).val());
});
});

 

// Load Regions
function loadRegions(selector, countryId) {
varurl='/users/places/countries.json?data%5BProfile%5D%5Bprofile_country_id%5D='+countryId;
 
$.getJSON(url ,function(resp) {
varselect=$(selector);
 
select.material_select('destroy');
select.empty();
$.each(resp, function(id, title) {
$('<option>').val(id).text(title).appendTo(select);
});

 

select.material_select();
});
}

Sebastian Kaczmarek staff pro premium commented 4 years ago

Sorry for asking you about so many things, but I really want to address the issue. Could you please use our Snippets editor to create the snippet and show actual behavior? https://mdbootstrap.com/snippets/


nextstepmedia pro commented 4 years ago

Hi Sebastian, thanks for addressing the issue! Ive uploaded a video on vimeo earlier to show the behavior: https://vimeo.com/287627163 password: 12345

Making a snippet of this will be hard as I do an ajax request to the db of our complex platform in order to get the data. Others experience the same issues though.

Remember the behavior is somewhat less worse at the moment but it takes like 20 seconds on some devices before the select elements are refreshed. The more data I fetch the longer the freeze it seems. My current stack (older MDB) has no delay at all and switches the data like a charm.


nextstepmedia pro commented 4 years ago

@Sebastian Kaczmarek Has there been an action to actively fix this bug on the short term?


Sebastian Kaczmarek staff pro premium commented 4 years ago

@nextstepmedia Sorry for the late answer, there is a lot of things going on in MDB at the moment. After an investigation, it looks like it's a bigger problem than I thought and as such, it won't be fixed in the nearest release. For now, you have to use your temporary fix. I'll keep you updated once it's fixed.


nextstepmedia pro commented 4 years ago

@Sebastian Kaczmarek Thanks for telling me how it is, Im a bit disappointed about the bugfixing and updating process as MDB is now a broken product for companies that need dynamic data in forms. I would really recommend versioning so we can see what version is stable. 

The workaround that you mentioned is not working at all, on mobile the freeze still takes up about 20 seconds which in unacceptable and will cost us thousands a day if we would deploy that. Either way I'm really hoping a fix will come soon as I could not update MDB for 2,5 months already. That makes it really hard for me to sell this stack to our stakeholders.

I know its not your call so thanks for trying to help us out and keeping us up to date. Please make sure this stays in the light of the dev team so this will be resolved in time.


Sebastian Kaczmarek staff pro premium answered 4 years ago

I am sorry for the inconveniences. Indeed, there is a problem with our code. To be more specific, in the material-select.js file, there is a method called enableValidation(). Going further, there is a code on line 223, which looks like this:
this.$nativeSelect.attr('style', `${this.$nativeSelect.attr('style')} display: inline!important;`);
As you can see, it copies the styles of the native select and adds additional style. The bug here is that it adds it always, no matter if the style is present there or not. So as the temporary fix, you can add an if statement and conditionally add the style if it's not present. For example:
if (this.$nativeSelect.attr('style').indexOf('inline!important') === -1) {
    this.$nativeSelect.attr('style', `${this.$nativeSelect.attr('style')} display: inline!important;`);
}
Then, you will have to recompile and minify the MDB package to have it in the mdb.min.js file. Second approach is to edit the mdb.js file directly (in the exact same way) and re-minify the file to have it in the mdb.min.js file. Anyway, this is a temporary fix and keep in mind that it will be fixed in the nearest release so it won't be needed anymore. Hope it helps!

nextstepmedia pro commented 4 years ago

This is the rule I have on 223 in material-select.js: var classes = $nativeSelectChild.attr('class'); On rule 244 I did see the line of code you mentioned So I changed it to: if (this.$nativeSelect.attr('style').indexOf('inline!important') === -1) { this.$nativeSelect.attr('style', ${this.$nativeSelect.attr('style')} display: inline!important;); } When I use this code and put a console log in there it does not get registered. Also my memory is still filling up when it freezes and still crashes the browser. Altough it seems that its much less worse as before. A second change of the select element will completely freeze the page just like before.

nextstepmedia pro commented 4 years ago

I am sure I am using the right file. A console log at the root of the script proved that to me.

nextstepmedia pro commented 4 years ago

Am I doing something wrong? As this doesn't fix it for me

Huichofer pro commented 4 years ago

Seems the .empty() call needs to happen before the destroy. See my last answer in this post.

Huichofer pro answered 4 years ago

Hi Sebastian, I have the exact same problem nextstepmedia reported. I tried the temporary solution provided but still freezing and crashing the browser after a few updates to the select element. For testing purposes I used mdb.js file instead of its minified version and changed that same code in line 2074 along with the material-select.js file. Here's a sample of my code:
$("#ddlLeagues").change(function () {
  $("#ddlTemplates").material_select("destroy");
  var league = $("#ddlLeagues").children("option").filter(":selected").val();
  $.getJSON("/api/leagues/" + league + "/templates")
    .done(function (data) { 
      $("#ddlTemplates")
        .empty()
        .append("<option value='' selected='selected'></option>");
      $.each(data, function (index, item) {
        $("#ddlTemplates").append($("<option>", { value: item.id }).text(item.name));
      });
    });
  $("#ddlTemplates").material_select();
});
 

Sebastian Kaczmarek staff pro premium answered 4 years ago

Guys, After deeper investigation, I have found that the source of the problem was not laying in the duplicating styles at all. In fact, the issue here was MutationObservers which were not disconnected before re-rendering the Material Select so the observers were multiplying exponentially with each select change. It has been resolved in the version 4.5.10. We have tested it in a variety of scenarios and all started to work properly after the fix. Also, since version 4.5.9 there is no need to manually destroy and initialize the select before and after each change. You just need to initialize it once and that's it. You can add and delete as many options as you wish and no manual reinitialization is needed.

hockchuan commented 4 years ago

It does not work with multiple dropdowns. HTML
Script $(document).ready(function() { $('.mdb-select').material_select(); }); $(document).on("change", "#select1", function () { var $select2 = $("#select2"); $select2.empty(); $select2.append($("").attr("value", "").text("Choose one")); for (var i = 0; i < 200; i++) { var ri = Math.floor(Math.random() * 10); $select2.append($("").attr("value", ri).text("Option " + ri)); } var $select3 = $("#select3"); $select3.empty(); $select3.append($("").attr("value", "").text("Choose one")); for (var i = 0; i < 200; i++) { var ri = Math.floor(Math.random() * 10); $select3.append($("").attr("value", ri).text("Option " + ri)); } }); Only the list in select2 is being updated correctly. The list in select3 is unchanged although I had already changed the list in select3 via Javascript. What am I missing?

Sebastian Kaczmarek staff pro premium commented 4 years ago

Ok, I see. It seems like a bug. We'll fix it with the next update. At the moment, just call $select3.materialSelect() again after initializing the options list

nextstepmedia pro commented 4 years ago

It does not seem resolved in the latest version (4.5.13) if you use more as one select dropdown. The effect gets worse as more options are loaded. When will this be resolved?

$('document').ready(function() {
// Initialize next, prev & submit button
initEvents();

 

// Populate & link countries and regions
varcountrySelect=$('#ProfileProfileCountryId');
varcountryId=countrySelect.val()

 

loadRegions('#ProfileProfileProvinceId', countryId);

 

countrySelect.change(function(event){

 

loadRegions('#ProfileProfileProvinceId', $(this).val());
});
});
// Load Regions
function loadRegions(selector, countryId) {
varurl='/users/places/countries.json?data%5BProfile%5D%5Bprofile_country_id%5D='+countryId;
 
$.getJSON(url ,function(resp) {
varselect=$(selector);
 
select.material_select('destroy');
select.empty();
$.each(resp, function(id, title) {
$('<option>').val(id).text(title).appendTo(select);
});

 

select.material_select();
});
}

hockchuan commented 4 years ago

yes, it's still not fixed. hope it will get fixed in the next version.

the workaround is not acceptable as it adds a lot of delay for the dropdown with many items.


kellyjromer pro premium priority answered 4 years ago

@Sebastian Kaczmarek We are having the same problem with the page becoming unresponsive due to the bug/leak in Material Select. This is a critical capability for us as we have many contextual/dynamic fields on our pages. I saw you say that it's a bigger problem than you thought and would not be fixed in the next release. Do you have any idea when it will be resolved? We need to know that as we can't go live with our new page designs until this is resolved. And I am not willing to have my team spend time on a temporary workaround as I am hoping your team will fix this standard website functionality ASAP. Thanks!

kellyjromer pro premium priority commented 4 years ago

@nextstepmedia Have you heard anything further on this?


hockchuan commented 4 years ago

May I know what's the temporary workaround? I am also facing the same unresponsive issue.


Sebastian Kaczmarek staff pro premium commented 4 years ago

Please try adding data-stop-refresh="true" to the select element. It should disable the feature connected with that. See https://mdbootstrap.com/docs/jquery/changelog/#v4-5-9


nextstepmedia pro commented 4 years ago

@kellyjromer Nope, no updates as of yet, is this fix working for you? @Sebastian Kaczmarek I will try that out! hope it works!!


kellyjromer pro premium priority commented 4 years ago

It does look like this is working for us...


hockchuan commented 4 years ago

Yes, the data-stop-refresh workaround is working for me.


bissounet answered a year ago

Apparently, despite its age, this problem has still not been resolved. This despite style="data-stop-refresh:true" and more recent support's advice to add this js code: $ ('# select_1'). Change (function () {... $ ('# select_2'). materialSelect ("destroy"); $ ("# select_2"). removeAttr ("disabled"); ... ajax ... $ ("# select_2"). materialSelect (); }

Why sell these components if there are not fonctionnal ?


Marcin Luczak staff commented a year ago

Hi @bissounet, I am sorry to hear you are facing problems with our component. If you need help with a part of your code not working due to setting dynamic content for the material select components please paste the snippet or a chunk of your code. We will try to help as best as we can.

Regards, Marcin


bissounet commented a year ago

Hi Marcin, making a snippet of this will be hard as I do an ajax request to the db of my website in order to get the data. Others experience the same issues though as described above. To sum up : the 2nd select (which depends on the first) works normaly the first time. But when I select another value in the first select, the list update of the 2nd is OK, but as I select a value in this 2nd select, everything freezes. If you really want me to paste a piece of my js code I can, but I'm not sure it will help.


Marcin Luczak staff commented a year ago

I get the idea of your application now. The general fix with working on Material Select dynamic content is to reinitialize the Material Select element after the dynamic update. You can check working example similar to your project here: https://mdbootstrap.com/snippets/jquery/grzegorz-bujanski/2617166#js-tab-view

If you want to make it use ajax calls please also look at this example: https://mdbootstrap.com/snippets/jquery/grzegorz-bujanski/2014875#js-tab-view

I hope this will help you make your Material Select works smoothly.

Regards, Marcin


bissounet commented a year ago

Sorry for the inconvenience Marcin, the error was on my side. In fact I have 3 chained selects, I made a mistake in the code to populate the 3rd. The js + ajax code was too long and too complex between $ ('# select_3'). Empty (); and $ ("# select_3"). materialSelect (); So I put this last instruction earlier in the code and everything works just fine. I am not sure of myself, but I think the problem was related to the fact that I am working in ajax with the POST method (synchro), and the successive waits after the 1st instruction were too long. It even seems that there is some kind of accumulation of expectations between the 2 instructions? .. In any case, thank you again for your examples to fix my issue! Regards, Jean-Luc


Marcin Luczak staff commented a year ago

I'm happy that I could help, and everything seems to be working fine now.

Best, Marcin


bissounet commented a year ago

I spoke too quickly ... after more than 6 requests through selects, I end up with the same crash. And the debugging console tells me: "Script terminated by timeout" by signaling the responsible files 42 times: mainly "jquery.min.js? Ver = 3.5.1: 2" and "MDB-Pro-Basic_4.19.2 / js / mdb.min.js? ver = 1.0.0: 25 ". The only time my js file is involved is at the line that invokes: "$ (" # select_3 "). MaterialSelect ();". So it seems to me that there is really a problem with the mdb.min.js.


bissounet commented a year ago

OK, issue fixed with "data-stop-refresh='true'" in the selects...


Marcin Luczak staff commented a year ago

That' a good news @bissounet :)


bissounet commented a year ago

Unfortunately I come back with the same problem. Apparently your select system could not be repaired. It is still the same MDB 4.19.2 version that is used, it has not been updated since I bought it. I use these mdb select components a lot in my site, they are filled by ajax requests linked to a database. After a few selections, the select which worked 2 or 3 times finaly freezes and blocks the site. If at least I knew if you had succeeded in solving this problem with MDB 5 Pro I might invest, but now I no longer have confidence.


bissounet commented a year ago

Unfortunately I come back with the same problem. Apparently your select system could not be repaired. It is still the same MDB 4.19.2 version that is used, it has not been updated since I bought it. I use these mdb select components a lot in my site, they are filled by ajax requests linked to a database. After a few selections, the select which worked 2 or 3 times finaly freezes and blocks the site. If at least I knew if you had succeeded in solving this problem with MDB 5 Pro I might invest, but now I no longer have confidence.


Arkadiusz Idzikowski staff commented a year ago

@bissounet Could you provide a simple HTML/JS example code and information about how we can reproduce this problem step by step (a new snippet would be the best in this case)?

We understand that you use ajax calls to a private database and we don't expect you to share production code, but we can easily replace this part on our end. We just want to make sure that we work on the same example so we can help you to resolve this issue (or to make sure that you can migrate to MDB5 without a problem).


Please insert min. 20 characters.

FREE CONSULTATION

Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.

Status

Answered

Specification of the issue
  • User: Pro
  • Premium support: No
  • Technology: MDB jQuery
  • MDB Version: 4.5.9
  • Device: All
  • Browser: all
  • OS: all
  • Provided sample code: No
  • Provided link: No