129

I am currently working with materialize CSS and it seems I've gotten snagged with the select fields.

I'm using the example provided from their site but unfortunately it it's rendering in the view whatsoever. I was wondering if someone else might be able to help.

What I am trying to do is create a row with 2 end spacers that provide padding - then within the inner two row items there should be a search text input and a search select dropdown.

This is the example I'm working from: http://materializecss.com/forms.html

Thank you in advance.

Here is the snippet of code in question.

<div class="row">
<form class="col s12">
    <div class="row">
        <div class="input-field col s2"></div>
        <div class="input-field col s5">
            <input id="icon_prefix" type="text" class="validate" />
            <label for="icon_prefix">Search</label>
        </div>
        <div class="input-field col s3">
            <label>Materialize Select</label>
            <select>
                <option value="" disabled="disabled" selected="selected">Choose your option</option>
                <option value="1">Option 1</option>
                <option value="2">Option 2</option>
                <option value="3">Option 3</option>
            </select>
        </div>
        <div class="input-field col s2"></div>
    </div>
</form>

Ryan Rentfro
  • 1,642
  • 3
  • 16
  • 18

14 Answers14

253

Because they override the browser default, the select styling needs Javascript to run. You need to include the Materialize Javascript file, and then call

$(document).ready(function() {
    $('select').formSelect();
    // Old way
    // $('select').material_select();
});

after you've loaded that file.

SeeoX
  • 565
  • 3
  • 18
jameslittle230
  • 3,098
  • 1
  • 14
  • 7
  • 25
    Otherwise you can use the browser default and not initialisation is required: ` – Shwaydogg Sep 30 '15 at 13:43
  • 9
    Latest changelog says this: `Rename plugin call .material_select() to .formSelect()` – Shod Nov 14 '18 at 06:03
  • 1
    Don't write this in $( document ).ready(function() { otherwise it won't work – HN Singh Jan 15 '19 at 12:03
  • Sheesh! I've beating my head against a brick wall for hours trying to figure this out... Thanks.... – Clyde Jan 30 '20 at 08:57
  • I was working on a project (Django + materialize). Stucked for two days because the Select wasn't working. I thought I do wrong with Django. When I did view-source, then I realized that everything is ok from Django. I copied the whole HTML code try to run it in the browser. Finally, I came to the conclusion that It was the fault of " $('select').formSelect();". Thanks. – Shaida Muhammad May 11 '21 at 12:59
53

The design of select functionality in materialize CSS is, in my opinion, a pretty good reason not to use it.

You have to initialize the select element with material_select(), as @littleguy23 mentions. If you don't, the select box is not even displayed! In an old-fashioned jQuery app, I can initialize it in the document ready function. Guess what, neither I nor many other people are using jQuery these days, nor do we initialize our apps in the document ready hook.

Dynamically created selects. What if I am creating selects dynamically, such as happens in a framework like Ember which generates views on the fly? I have to add logic in each view to initialize the select box every time a view is generated, or write a view mixin to handle that for me. And it's worse than that: when the view is generated, and in Ember terms didInsertElement is called, the binding to the list of options for the select box may not have been resolved yet, so I need special logic observing the option list to wait until it's populated before making the call to the material_select. If the options change, as they easily might, material_select has no idea about that and does not update the dropdown. I can call material_select again when the options change, but it appears that that does nothing (is ignored).

In other words, it appears that the design assumption behind materialize CSS's select boxes is that they are all there at page load, and their values never change.

Implementation. From an aesthetic point of view, I am also not in favor of the way materialize CSS implements its dropdowns, which is to create a parallel, shadow set of elements somewhere else in the DOM. Granted, alternatives such as select2 do the same thing, and there may be no other way to achieve some of the visual effects (really?). To me, though, when I inspect an element, I want to see the element, not some shadow version somewhere else that somebody magically created.

When Ember tears down the view, I am not sure that materialize CSS tears down the shadow elements it has created. Actually, I'd be quite surprised if it does. If my theory is correct, as views are generated and torn down, your DOM will end up getting polluted with dozens of sets of shadow dropdowns not connected to anything. This applies not only to Ember but any other MVC/template-based OPA front-end framework.

Bindings. I also have not been able to figure out how to get the value selected in the dialog box to bind back to anything useful in a framework like Ember that invokes select boxes through a {{view 'Ember.Select' value=country}} type interface. In other words, when something is selected, country is not updated. This is a deal-breaker.

Waves. By the way, the same issues apply to the "wave" effect on buttons. You have to initialize it every time a button is created. I personally don't care about the wave effect, and don't understand what all the fuss is about, but if you do want waves, be aware that you'll spend a good portion of the rest of your life worrying about how to initialize every single button when it's created.

I appreciate the effort made by the materialize CSS guys, and there are some nice visual effects there, but it's too big and has too many gotchas such as the above to be something that I would use. I'm now planning to rip out materialize CSS from my app and go back either to Bootstrap or a layer on top of Suit CSS. Your tools should make your life easier, not harder.

  • 3
    Thank you for the extensive response. It's very informative and I agree with a lot of the sentiments you've expressed. I do really like materialize CSS and their approaches with a lot of things. I get exactly what you're saying and have been thinking a lot about all the 'effects' modern apps will demand. I'm not sure those types of designs and concepts fit into large scale software just yet. I sure do like the look and concepts though. Thank you again. – Ryan Rentfro Feb 02 '15 at 02:29
  • Great response. Running into SELECT issues with Materialize as well, like click events on the scrollbar dismissing the OPTIONs list. @torazaburo What did you end up going with? Back to Bootstrap? – Sean O Apr 16 '15 at 15:19
  • I spent enough time on converting my most of web pages and forms to materialize, but now stuck in how to solve the select issue. Its really bad, the materializecss has huge traffic but still do not solve this minor issue. If you are evaluating to use it for some consumer product, wait until it mature – Asif Shahzad May 24 '15 at 08:05
  • @torazaburo About bindings: for me, using package ember-cli-materialize and then `{{md-select content=model.blah optionValuePath='content.id' optionLabelPath='content.label' value=someField}}` did the trick: it updates the `someField` property in the controller. – LexLythius May 28 '15 at 22:23
  • 9
    You can use ` – Shwaydogg Sep 30 '15 at 13:41
  • I suppose all this is somewhat moot now that Google has published its own Material Design Lite library. –  Sep 30 '15 at 14:20
  • It appears that the Materialize selectors are not reactive within Meteor either when a value of a Session changes. I'm struggling with this right now. – flimflam57 Jun 05 '16 at 23:22
  • @Shwaydogg using `browser-default` will change the select's appearance. We want the functionally working, that's all – Bernardo Dal Corno Mar 07 '18 at 07:12
9

@littleguy23 That is correct, but you don't want to do it to multi select. So just a small change to the code:

$(document).ready(function() {
    // Select - Single
    $('select:not([multiple])').material_select();
});
DFlores009
  • 91
  • 1
  • 2
9

This worked for me, no jquery or select wrapper with input class, just material.js and this vanilla js:

document.addEventListener('DOMContentLoaded', function() {
    var elems = document.querySelectorAll('select');
    var instances = M.FormSelect.init(elems);
});

enter image description here enter image description here

As you can tell I got the materialize css actual style and not the browsers default.

lomelisan
  • 908
  • 10
  • 15
8

This works too: class = "browser-default"

Abel
  • 93
  • 1
  • 6
3

The solution that worked for me is by calling the 'material_select' function after the options data has been loaded. If you print out the value of OptionsList.find().count() to the console it's first 0 then a few milliseconds later the list gets populated with data.

Template.[name].rendered = function() {
    this.autorun(function() {
        var optionsCursor = OptionsList.find().count();
        if(optionsCursor > 0)
        {
            $('select').material_select();
        }
    });
};
jkdev
  • 11,360
  • 15
  • 54
  • 77
Brandiqa
  • 51
  • 1
  • 2
  • 1
    Nice find Brandiqa! I had called `$('select').material_select();` from `AppComponent.ngOnInit()`, but you need to call it after the `` html is rendered, which I did in `dropdown.component.ts`. The fix was to call it from `ngOnInit()` within whichever component uses the dropdowns. – Levi Fuller Jun 11 '16 at 17:53
3

If you're using Angularjs, you can use the angular-materialize plugin, which provides some handy directives. Then you don't need to initialize in the js, just add material-select to your select:

<div input-field>
    <select class="" ng-model="select.value1" material-select>
        <option ng-repeat="value in select.choices">{{value}}</option>
    </select>
</div>
Artemis_134
  • 173
  • 1
  • 3
  • 14
2

For me none of the other answers worked because I am using the latest version of MaterializeCSS and Meteor and there is incompatability between the jquery versions, Meteor 1.1.10 uses jquery 1.11 (overriding this dependancy is not easy and will probably break Meteor/Blaze) and testing Materialise with jquery 2.2 works fine. See https://stackoverflow.com/a/34809976/2882279 for more info.

This is a known issue with dropdowns and selects in materialize 0.97.2 and 0.97.3; for more info see https://github.com/Dogfalo/materialize/issues/2265 and https://github.com/Dogfalo/materialize/commit/45feae64410252fe51e56816e664c09d83dc8931.

I'm using the Sass version of MaterializeCSS in Meteor and worked around the problem by using poetic:materialize-scss@1.97.1 in my meteor packages file to force the old version. The dropdowns now work, old jquery and all!

Community
  • 1
  • 1
Mozfet
  • 359
  • 3
  • 12
1

Call the materialize css jquery code only after the html has rendered. So you can have a controller and then fire a service which calls the jquery code in the controller. This will render the select button alright. How ever if you try to use ngChange or ngSubmit it may not work due to the dynamic styling of the select tag.

Nitish Phanse
  • 552
  • 1
  • 9
  • 16
1

Only this worked for me:

$(document).ready(function(){
    $('select').not('.disabled').formSelect();
});
Igor Shumichenko
  • 394
  • 3
  • 12
0

I found myself in a situation where using the solution selected

$(document).ready(function() {
$('select').material_select();
}); 

for whatever reason was throwing errors because the material_select() function could not be found. It was not possible to just say <select class="browser-default... Because I was using a framework which auto-rendered the the forms. So my solution was to add the class using js(Jquery)

<script>
 $(document).ready(function() {
   $('select').attr("class", "browser-default")
});

unlockme
  • 3,897
  • 3
  • 28
  • 42
0

First, make sure you initialize it in document.ready like this:

$(document).ready(function () {
    $('select').material_select();
});

Then, populate it with your data in the way you want. My example:

    function FillMySelect(myCustomData) {
       $("#mySelect").html('');

        $.each(myCustomData, function (key, value) {
           $("#mySelect").append("<option value='" + value.id+ "'>" + value.name + "</option>");
        });
}

Make sure after you are done with the population, to trigger this contentChanged like this:

$("#mySelect").trigger('contentChanged');
Alejandro Bastidas
  • 1,452
  • 2
  • 20
  • 26
0

For default browser,

<head>
     select {
            display: inline !important;
         }
</head>

Or the Jquery solution after the link t Jquery library and your local/CDN materialize files

<script>
(function($){
  $(function(){
    // Plugin initialization
    $('select').not('.disabled').formSelect();
  }); 
})(jQuery); // end of jQuery name space

I really like this framework, but what on earth to have display:none...

user2060451
  • 2,576
  • 3
  • 24
  • 31
-5

Just to follow up on this since the top answer recommends not using materializecss... in the current version of materialize you no longer need to initialize selects.

user2386854
  • 173
  • 1
  • 11