krescruz / angular-materialize

Angularjs directives for Materialize CSS Framework https://github.com/Dogfalo/materialize
MIT License
396 stars 129 forks source link

material-select not showing predefined value from ng-model #160

Closed jacek213 closed 8 years ago

jacek213 commented 8 years ago
    html:
    <select ng-model="editUserCtrl.state" material-select>
       <option value="active">Active</option>
       <option value="locked">Locked</option>
    </select>

    JS:
    vm.state = "active"

Result - when I open the page active option is not selected.

webbiesdk commented 8 years ago

See this: http://stackoverflow.com/questions/17606936/angularjs-dot-in-ng-model

You are storing a property directly on your controller, Angular doesn't handle that well with nested scopes.

It works for me when storing the state as an object.

jacek213 commented 8 years ago

Ok I got what I was wrong. It was not really stored as a property directly. I had it stored in vm.model.state. However, on controller init I made I request to backend to fetch the model. So before the request was done, vm.model.state was undefined. Because of that a third, blank option was prepended to select and the blank option was treated as active and locked was mistreated as active. That's a bug in my opinion. However, adding watch to select solves the issue.

webbiesdk commented 8 years ago

adding watch should only fix it, if the actual options were changed. If it is only the value in ng-model that was changed, then watch shouldn't make a difference.

If you look at this relevant code from the script:

$timeout(initSelect);
if (attrs.ngModel) {
    scope.$watch(attrs.ngModel, initSelect);
}
if ("watch" in attrs) {
    scope.$watch(function () {
        return element[0].innerHTML;
    }, function (oldVal, newVal) {
        if (oldVal !== newVal) {
            $timeout(initSelect);
        }
    });
}

You'll see that watch shouldn't do anything, except if the options change.

It might look further into it later, because it sounds weird.

webbiesdk commented 8 years ago

If you have some standalone code that demonstrates the issue (you can just use setTimeout() instead of a server call), then it would be nice if you send it my way.

jacek213 commented 8 years ago

There u go:

http://jsfiddle.net/Lvc0u55v/5129/

webbiesdk commented 8 years ago

That is perfect, thanks.

webbiesdk commented 8 years ago

Turns out you were right, adding watch was the right thing to do.

Having the state as "undefined" in the beginning adds an extra "ghost" option (that appears in the html), that disappears when the state is set to an actual value. This is the reason the watch actually made a difference, because the innerHTML is actually different.

I might add a note about it in the documentation.

webbiesdk commented 8 years ago

Or instead of mentioning it, I could just fix it.

If you include the above commit, you should no longer need to add the watch attribute.