LisPNZ
@LisPNZ
Почти фулстек

Как в компоненте отследить изменение полей для включения кнопок сохранения?

Есть поля date допустим 'name' и ''name_changed'.
На него повешено слежение:
watch:{
  name(val, old){
    this.name_changed = true;
  }
}

и в темплейте есть кнопка сохранения/отправки значения поля у которой :disabled="!name_changed", то есть кнопка изначально должна быть disabled, а после изменения значения пользователем должна "раздисейбливаться"
Поле name заполняется по axios запросу (в методе mounted).

Так вот, проблема в том, что видимо когда по первому запросу поле name заполняется, соответственно поле name_changed становится равно true и кнопка сохранения получается изначально доступна.
Как вариант я должен где то проверить при изменении name что это пользователь изменил а не программная инициация.
Конечно можно повесить слушатель на input и навесить своей логики , но она вылезет вся в template, а это как то не красиво. А в рабочем коде отслеживаемых полей много и будет каша в template
Хотелось бы провернуть все максимально в JS.
Кто то может делал подобное элегантно.
Примерный код набросал в комментарии ниже
  • Вопрос задан
  • 1642 просмотра
Решения вопроса 2
0xD34F
@0xD34F Куратор тега Vue.js
проблема в том, что видимо когда по первому запросу поле name заполняется, соответственно поле name_changed становится равно true и кнопка сохранения получается изначально доступна

Можно запускать слежение после получения данных. Вырезаете

watch:{
  name(val, old){
    this.name_changed = true;
  }
}

А в коллбек запроса, после установки значения name, добавляете:

this.$watch('name', () => this.name_changed = true);
Ответ написан
dubr
@dubr
пыхарь
Вотчеры - это обычно признак джейквири-программирования =)
Лучше сохранять оригинальные данные и их сравнивать с текущими. Так и честный changed будет (у вас скорее "touched").

Вот набросал примерно:
const api = {
  async getData() {
    return {name: 'Foo', email: 'foo@bar.com'};
  }
}

new Vue({
  el:'#app',
  template: `<div v-if="current">
    <input v-model="current.name" />
    <input v-model="current.email" />
    <button :disabled="!isChanged">submit</button>
  </div>`,
  data() {
    return {
      original: null,
      current: null,
    }
  },
  async created() {
    const data = await api.getData();
    this.original = JSON.stringify(data);
    this.current = data;
  },
  computed: {
    isChanged() {
      return JSON.stringify(this.current) !== this.original;
    }
  }
});

https://codepen.io/dubrowsky/pen/BvdKZE?editors=1010

UPD: Если нужен не changed, а touched - сделайте
<input type="text" v-model="name" @input="name_changed = true">
и будет счастие
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы