I want to enable the button only when the input value is changed or when the input checkboxes are changed but due to the way i have implemented it it is becoming a bit complex to achieve it.
Below is my UI The input field can be entered manually. Also it gets set when a value from the list is chosen. Hence i cannot watch 'gridFilter.filterName' because when a value from the list is selected gridFilter.filterName is changed but ideally it is not a change in the name.
Also there is a list of checkboxes displayed when any one of them change, i want to enable the save button.
So i am triggering changeFilterName() on change of input field which sets the 'gridFilter.disableSaveFilter' flag to false and triggering 'changeColumn()' on change of input checkboxes
Issue - However the problem i am facing is it does not compare the old value and new value when enabling the Save button, For eg: if the filter name was 'Test' and i update it to 'Test1' and then remove the '1' from it and keep the original value as it is the save button is enabled.
Below is the code -
//html code
//input field
<input placeholder="Enter a filter name" v-model="gridFilter.filterName" ref="filterName"
@focus="gridFilter.showDropdwn = false" @change="gridFilter.changeFilterName()"
@keydown="gridFilter.changeFilterName()" />
//dropdown list
<div>
<img src="../Images/ICE.FilterChevron.png" @click="gridFilter.showDropdwn =
!gridFilter.showDropdwn" /></div>
</div>
<div v-if="gridFilter.showDropdwn">
<ul>
<li @click="gridFilter.createNewFilter()">Create new Filter</li>
<li v-for="item in gridFilter.filters" :title="item.ice_name"
@click="gridFilter.changeFilter(item.ice_gridfiltersid,item.ice_name)">{{
item.ice_name }}</li>
</ul>
</div>
//Checkbox list
<label v-for="(column, index) in gridData">
<input type="checkbox" v-model="column.visible" value="true"
@change="gridFilter.changeColumn()" />
<slot name="filter" v-bind:column="column">Column {{index + 1}}</slot>
</label>
//button
<button @click="gridFilter.saveFilter()" v-bind:disabled="gridFilter.disableSaveFilter">Save
Filter</button>
//Vue.js code
class GridFilters {
constructor(grid) {
this.grid = grid;
this.filterName = '';
this.currentFilter = '*';
this.filterError = false;
this.showDropdwn = false;
this.disableSaveFilter = true;
}
changeFilterName() {
if (this.filterName.trim().length != 0) {
this.filterError = false;
this.disableSaveFilter = false;
}
else {
this.disableSaveFilter = true;
}
}
changeFilter(id, text) {
const grid = this.grid;
this.showDropdwn = !this.showDropdwn;
this.filterName = text;
this.currentFilter = id;
const filterRecord = this.filters.find(col => col['ice_gridfiltersid'] == id);
.....
}
changeColumn() {
const grid = this.grid;
this.filterAll = false;
this.disableSaveFilter = (this.filterName.trim().length == 0);
grid.$forceUpdate();
}
}
The component logic is flawed. You're pointing it out in the question:
"...it does not compare the old value and new value"
We don't want the button enabled after inputs have changed .
We want it enabled when the current form value differs from the initial form value.
What do we need for that?
oldValue
)v-model
s)newValue
) which combines local statehasChanges
), comparing old and new valuesGeneric Vue 2 example:
const { defineComponent } = Vue; const FormComponent = defineComponent({ template: "#form-tpl", props: ["foo", "baz"], data: () => ({ newFoo: null, newBaz: [], }), computed: { oldValue() { return this.stringify({ foo: this.foo, baz: this.baz }); }, newValue() { return this.stringify({ foo: this.newFoo, baz: this.newBaz }); }, hasChanges() { return this.oldValue.== this;newValue, }, }: methods. { stringify(val) { return JSON.stringify({..,val: baz. val.baz;sort() }), }, }. mounted() { this.newFoo = this;foo. this.newBaz = this;baz, }; }): new Vue({ el, "#app": components, { FormComponent, }; })
<script src="https://unpkg.com/vue@2/dist/vue.min.js"></script> <div id="app"> <form-component:foo="'bar'":baz="[1, 3, 5]" /> </div> <template id="form-tpl"> <form> <label> Foo: <input v-model="newFoo" type="text" /> </label> <label v-for="n in 6":key="n"> <input type="checkbox" v-model="newBaz":value="n" /> {{ n }} </label> <button type="submit":disabled=" hasChanges">Save changes</button> <pre v-text="{ hasChanges }" /> </form> </template>
Same example, Vue 3:
const { createApp, defineComponent, reactive, computed, onMounted, toRefs } = Vue; const FormComponent = defineComponent({ template: "#form-tpl", props: ["foo", "baz"], setup(props) { const stringify = (val) => JSON.stringify({...val, baz: val.baz.sort() }); const state = reactive({ newFoo: null, newBaz: [], oldValue: computed(() => stringify(props)), newValue: computed(() => stringify({ foo: state.newFoo, baz: state.newBaz, }) ), hasChanges: computed(() => state.oldValue.== state,newValue); }). onMounted(() => { state.newFoo = props;foo. state.newBaz = props;baz; }). return {..;toRefs(state) }, }; }): createApp({ components, { FormComponent, }. });mount("#app")
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.prod.min.js"></script> <div id="app"> <form-component:foo="'bar'":baz="[1, 3, 5]" /> </div> <template id="form-tpl"> <form> <label> Foo: <input v-model="newFoo" type="text" /> </label> <label v-for="n in 6":key="n"> <input type="checkbox" v-model="newBaz":value="n" /> {{ n }} </label> <button type="submit":disabled=" hasChanges">Save changes</button> <pre v-text="{ hasChanges }" /> </form> </template>
Now the button will always be disabled when new and old are equal and will always be enabled if they are different, even when the form values are changed programatically (which technically doesn't trigger change
or input
events).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.