Reputation: 6896
On my MVC project I have a View with 3 forms and one KO ViewModel
.
On each form I have a reset button to clear its own fields.
I can't use input type="reset"
because it doesn't update the observable values.
I can't either reset the View Model
because that will reset all the observables of the View Model
and I only need to reset the ones that are on the form that triggered the reset.
I can write 3 functions, one for each form and manually deleting each form fields like this:
this.onForm1Reset = function () {
this.field1('');
this.field2('');
//etc..
}
this.onForm2Reset = function () {
this.field3('');
this.field4('');
//etc..
}
this.onForm3Reset = function () {
this.field5('');
this.field6('');
//etc..
}
But I'm looking for a more global and a shorter solution.
I made a lot of researches online but couldn't find a good solution for that.
Any help would be very much appreciated.
Upvotes: 3
Views: 3341
Reputation: 43881
If you can group the forms' fields, you can use a with
binding on each form to provide a different context to the form members, so the reset
function (as a click handler) attached to a reset button will only be looking at the observables for its own form.
If you can't group the fields, a (less-preferred) possibility would be to run through the bound elements of the form containing the reset button, reset their values, and fire the change events for them. The commented-out code in my snippet would do that.
vm = {
fieldset1: {
field0: ko.observable(),
field1: ko.observable()
},
fieldset2: {
field2: ko.observable(),
field3: ko.observable()
},
fieldset3: {
field4: ko.observable(),
field5: ko.observable()
},
reset: function(data) {
for (var key in data) {
if (data.hasOwnProperty(key)) {
data[key]('');
}
}
};
ko.applyBindings(vm);
/*
$('body').on('click', '[type="reset"]', function() {
$(this.parentNode).find('[data-bind*="value:"]').each((index, item) => {
$(item).val('').change();
});
});
*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<form data-bind="with: fieldset1">
<input data-bind="value:field0" />
<input data-bind="value:field1" />
<input type="reset" data-bind="click: $parent.reset" />
</form>
<form data-bind="with: fieldset2">
<input data-bind="value:field2" />
<input data-bind="value:field3" />
<input type="reset" data-bind="click: $parent.reset" />
</form>
<form data-bind="with: fieldset3">
<input data-bind="value:field4" />
<input data-bind="value:field5" />
<input type="reset" data-bind="click: $parent.reset" />
</form>
Upvotes: 4
Reputation: 282
Would something like this work? Where you have a function to empty observables? Depending on the click of reset?
this.emptyObservablesRestForm1 = function () {
this.field1(false);
}
this.emptyObservablesRestForm2 = function () {
this.field2(false);
}
Upvotes: 0
Reputation: 166
You might also want to consider splitting your ViewModel into one separate VM per Form(Group of fields).
Using this approach you coud reset a Form by recreating the respective ViewModel.
Upvotes: 1
Reputation: 49095
A more practical solution would be to contain your view-model in an observable, and re-create the model upon resetting:
function MyViewModel()
{
this.field1 = ko.observable();
this.field2 = ko.observable();
// etc...
}
var model = {
data: ko.observable(new MyViewModel()),
reset: function() {
model.data(new MyViewModel());
}
};
ko.applyBindings(model);
And in your HTML:
<body data-bind="with: data">
...
<button data-bind="click: $root.reset">Reset</button>
</body>
See Fiddle
Update (as per your comment):
Since you don't want to replace the entire view-model but only reset certain fields, I assume you'll have to introduce a reset()
method to your model:
function MyViewModel()
{
this.field1 = ko.observable();
this.field2 = ko.observable();
this.reset = function() {
this.field1('');
this.field2('');
}.bind(this);
}
ko.applyBindings(new MyViewModel());
And in your HTML:
<button data-bind="click: reset">Reset</button>
Upvotes: 1