问题
I am currently building a Single Page App with knockout.js and Material Design Lite.
I have a form which allow creating (and persisting) a new entity. The first time the form is used, the floating label input works correctly. But after that, if I reset the values of the fields through knockout observables (i.e. set the field values to "" in order to be able enter the values for another new entity) the floating label doesn't reset: the floating label still floats above the field, while it should be displayed in grey in the field itself without floating anymore.
Note that if I manually enter into the field, add space, remove the space and exit the field, the reset behavior is working.
Here are the important excerpts from the code:
The form is defined following the Material Design Lite (see http://www.getmdl.io/components/index.html#textfields-section "text with floating label")
<form>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="field1" data-bind="value: field1" />
<label class="mdl-textfield__label" for="field1">Field1 floating label</label>
</div>
</form>
On the knockout side I have this code:
function MyViewModel() {
var self = this;
self.field1 = ko.observable();
....
self.resetForm = function () {
self.field1("");
}
....
In my JS, I create my ViewModel
var vm = new MyViewModel()
and, when I want to create a new entity, on this View Model I call
vm.resetForm();
in order to reset the field. The field is correctly set to the empty value, but the floating layout behavior (going back to initial state) is not triggered.
Thanks
回答1:
Your issue is discussed here. You need a custom binding handler to add and remove classes (particularly is-dirty
) to the div surrounding the input when the bound value changes.
A custom binding handler is a bit of work, but it will actually make your HTML cleaner. I've whipped up one for you below as an example, although it could surely stand some improvement.
This is a good read on the subject.
ko.bindingHandlers.mdlFloatingInput = {
init: function (element, valueAccessor, allBindingsAccessor, data, context) {
var $el = $(element),
$enclosingDiv = $('<div>').insertAfter($el),
$label = $('<label>'),
params = valueAccessor();
$el.attr('id', params.id);
$label.attr('for', params.id).text(params.label);
$el.addClass('mdl-textfield__input');
$label.addClass('mdl-textfield__label');
$enclosingDiv.addClass("mdl-textfield mdl-js-textfield mdl-textfield--floating-label").append($el).append($label);
ko.bindingHandlers.value.init(element, function () { return params.value; }, allBindingsAccessor, data, context);
},
update: function (element, valueAccessor, allBindingsAccessor, data, context) {
var params = valueAccessor(),
value = params.value();
ko.bindingHandlers.value.update(element, function () { return params.value; }, allBindingsAccessor, data, context);
$(element).parent()[value ? 'addClass' : 'removeClass']('is-dirty');
}
};
function MyViewModel() {
var self = this;
self.field1 = ko.observable('');
self.resetForm = function () {
self.field1("");
};
}
var vm = new MyViewModel();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//storage.googleapis.com/code.getmdl.io/1.0.5/material.min.js"></script>
<link rel="stylesheet" type="text/css" href="//storage.googleapis.com/code.getmdl.io/1.0.5/material.indigo-pink.min.css">
<form>
<input data-bind="mdlFloatingInput: {label: 'Field1 floating label', value: field1, id:'field1'}" />
<!--div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="field2" />
<label class="mdl-textfield__label" for="field2">Unbound floating label</label>
</div-->
</form>
<button data-bind="click:resetForm">Reset</button>
<div data-bind="text:field1"></div>
回答2:
You can simply use
<yourElement>.MaterialTextfield.change();
来源:https://stackoverflow.com/questions/32957407/material-design-lite-how-to-programatically-reset-a-floating-label-input-text