Угловая реактивная функция valueChanges формы для обнаружения и сохранения только измененных полей

После отправки формы я хочу зафиксировать только значения полей, которые были изменены.

Использование функции valueChanges в форме фиксирует каждое поле формы, и его нельзя пройти как массив, как я пытался сделать в своем коде ниже.

Я не уверен в каком-либо другом способе сравнения значений формы «до и после» и их сохранения там, где хранятся только измененные поля.

export class JobEditComponent implements OnInit {
jobNumber: any;
jobs: any[];
jobToEdit: Job;
job: any;
brands: Brand[];
jobForm: FormGroup;
bsConfig: Partial<BsDatepickerConfig>;
isFormReady: any;
jobId: number;
existingValues: string[] = [];
changedValues: string[] = [];


constructor(private route: ActivatedRoute,
  private jobService: JobService,
  private fb: FormBuilder,
  private router: Router,
  private alertify: AlertifyService) { }

ngOnInit() {
  this.route.params.subscribe(params => {
    this.jobNumber = +params['id'];
    });

    this.jobService.getJobToEdit().subscribe((jobs: Job[]) => {
      this.jobs = jobs;
    }, error => { console.log('error');
    }, () => {
      this.jobToEdit = this.jobs.find(j => j.id === this.jobNumber);
      this.editJobForm();
      this.onChanges();
    });

    this.getBrands();

    this.bsConfig = {
      containerClass: 'theme-blue'
    };
  }

onChanges(): void {
  this.jobForm.valueChanges.subscribe(val => {
    if (this.existingValues != null) {
      this.existingValues = val;
    }
  });
}


editJobForm() {
  this.jobForm = this.fb.group({
    jobNumber: [this.jobToEdit.jobNumber, Validators.required],
    item: [this.jobToEdit.item, Validators.required],
    status: [this.jobToEdit.status, Validators.required],
    orderedBy: [this.jobToEdit.orderedBy, Validators.required],
    orderDate: [this.jobToEdit.orderDate, Validators.required],
    quantity: [this.jobToEdit.quantity, Validators.required],
    unitPrice: [this.jobToEdit.unitPrice, Validators.required],
    lineValue: [this.jobToEdit.lineValue, Validators.required],
    dpAp: [this.jobToEdit.dpAp, Validators.required],
    eta: [this.jobToEdit.eta, Validators.required],
    detailStatus: [this.jobToEdit.detailStatus, Validators.required],
    comments: [this.jobToEdit.comments, null]
  }, ); this.isFormReady = true;
}

updateJob() {
  this.alertify.confirm('Are you sure you want save changes?', () => {
  this.jobId = this.jobToEdit.id;
  this.jobToEdit = Object.assign({}, this.jobForm.value);
  this.jobService.editJob(this.jobToEdit, this.jobId).subscribe(() => {
    this.alertify.success('Update successful');
    **for (let i = 0; i < this.existingValues.length; i++) {
      if (this.jobToEdit[i] !== this.existingValues[i]) {
         this.changedValues[i] = this.jobToEdit[i];
      }
    }**
    console.log(this.changedValues);
  }, error => {
    this.alertify.error(error);
  }, () => {
    this.router.navigate(['/home']);
  });
});
}

}


person Ryn9011    schedule 15.03.2018    source источник


Ответы (2)


Попробуйте это для своего цикла:

// declare changedValues as key -> val object (not array)
changedValues: { [key: string]: any } = {};

Object.keys(this.existingValues).forEach(i => {
  if (this.jobToEdit[i] !== this.existingValues[i]) {
     this.changedValues[i] = this.jobToEdit[i];
  }
}

ОБНОВЛЕНИЕ

тот же цикл с использованием синтаксиса for (key in object), предложенный @Alex:

for (let key in this.existingValues) {
  if (this.jobToEdit[key] !== this.existingValues[key]) {
     this.changedValues[key] = this.jobToEdit[key];
  }
}
person Andriy    schedule 15.03.2018
comment
Предполагая, что я правильно вас понял, Typescript выдает следующую ошибку: 'ts] Аргумент типа "число" не может быть присвоен параметру типа "(значение: строка, индекс: число, массив: строка[]) => void". пусть i: число' for (пусть i = 0; i ‹ this.existingValues.length; i++) { Object.keys(this.existingValues).forEach(i) => { if (this.jobToEdit[i] !== this.existingValues[i]) { this.changedValues[i] = this.jobToEdit[i]; } } - person Ryn9011; 16.03.2018
comment
У меня есть опечатка в моем коде (')' после 'i'), также я предположил, что this.jobToEdit[i] это строка, но я думаю, что это может быть и объект (я изменю его тип на 'любой'), поэтому я обновит мой код с этими двумя исправлениями - person Andriy; 16.03.2018

Вы можете проверить значения при отправке вместо использования valueChanges, поэтому, если ваша форма будет выглядеть так:

constructor(private fb: FormBuilder) {
  this.myForm = this.fb.group({
    field1: [this.values.field1],
    field2: [this.values.field2],
    field3: [this.values.field3]
  })
}

вы можете при отправке проверить значения свойств и посмотреть, совпадают ли они:

// 'values' is 'myForm.values'
onSubmit(values) {
  let changed = {};
  for (let ctrl in values) {
    if(values[ctrl] !== this.values[ctrl]) {
      changed[ctrl] = values[ctrl];
    }
  }
  console.log(changed);
}

Вот

StackBlitz

person AJT82    schedule 16.03.2018