Сравнение суммы в реактивных формах в Angular

Мне нужно сравнить amount с applied_amount. Однако они находятся на разных элементах управления, но находятся в одной и той же группе форм. Как мне проверить, больше ли «сумма», чем «applied_amount»? Вот код ниже.

 this.reportForm = this.fb.group({
                employee_id: [null, Validators.required],
                outlet_id: [null, Validators.required],
                grand_total: new FormControl({value: null, disabled: true}, Validators.required),
                rows: this.fb.array([]),
                applied_amount: [null, Validators.required],
            });


initGroup() {
        let rows = this.reportForm.get('rows') as FormArray;
        rows.push(this.fb.group({
            expense_account: ['', Validators.required],
            description: ['', Validators.required],
            amount: ['', Validators.required],
        },{validator: this.customValidator(rows)}))
    }



customValidator(group: any) {
        if ((group.controls.amount.value > group.parent.parent.controls.applied_amount.value)) {
            return { out1: true }
        }
        return null;
    }

person Joseph    schedule 12.02.2018    source источник
comment
Что именно не работает?   -  person Boris Lobanov    schedule 12.02.2018
comment
@Борис Лобанов. Я не знаю, как сравнить «applied_amount» с «amount». Я должен сравнить, если «количество» больше, чем «applied_amount».   -  person Joseph    schedule 12.02.2018


Ответы (3)


Прежде всего, вы не должны вызывать метод customValidator, как уже упоминалось @Boris Lobanov

Он говорит, что не может прочитать родителя неопределенного

Это потому, что когда angular создает от FormGroup до FormBuilder::group, он также вызывает валидаторы, но у текущей группы еще нет родителя. Родитель будет установлен только после FormArray::push.

Таким образом, решение может выглядеть так:

validator: this.customValidator
...

customValidator(group: any) {
  if (!group.parent ) {
      return;
  }
  ...

Я также запускаю проверку для всех строк при изменении applied_amount.

HTML

<input type="number" formControlName="applied_amount" (ngModelChange)="validateAllRows()">

ts

validateAllRows() {
  const rows = this.reportForm.get('rows') as FormArray;

  rows.controls.forEach(group => {
    group.updateValueAndValidity();
  })
}

Пример Ng-run

Другое решение почти такое же, как ваше:

validator: this.customValidator.bind(rows)
...

customValidator(this: FormArray, group: any) {
  if (group.controls.amount.value > this.parent.controls['applied_amount'].value) {
    return { out1: true }
  }
  return null;
}

Здесь я использую метод Function.prototype.bind для передачи FormArray непосредственно вашему валидатору.

person yurzui    schedule 13.02.2018
comment
Спасибо Юрзуи. Но когда моя проблема заключается в том, что есть несколько строк суммы. Как мне проверить, не больше ли их суммы, чем apply_amount? - person Joseph; 13.02.2018
comment
Да. Но я не могу сохранить вашу демонстрацию. - person Joseph; 13.02.2018
comment
я проверю это позже - person yurzui; 13.02.2018
comment
Вот. ng-run.com/edit/ - person Joseph; 13.02.2018
comment
первый. я набираю 1000 в поле apply_amount. Затем для первой суммы я набираю 500, затем для второй суммы я набираю 510. Должна выводиться ошибка. - person Joseph; 13.02.2018
comment
Но ваш валидатор проверяет только значение текущей группы. Вместо этого вам нужно суммировать все значения - person yurzui; 13.02.2018
comment
Да, это моя проблема. Как бы я это сделал? Я тоже не хочу показывать итог? Я могу добиться этого, НО я не хочу показывать общую сумму. - person Joseph; 13.02.2018
comment
Вы что-то упускаете. Почему, если я наберу 1000 в поле apply_amount. И затем я набираю 999 в первом вводе и 2 во втором вводе. Выдает ошибку. НО проблема возникает, когда я возвращаюсь к первому входу и меняю 999 на 998. Группа действительно должна быть правдой, почему она все еще ложна? - person Joseph; 13.02.2018
comment
Это не проблема. Проблема возникает, когда я возвращаюсь к первому вводу и меняю 999 на 998. Допустимая группа должна быть истинной, почему она все еще ложная - person Joseph; 13.02.2018
comment
Тот самый случай, о котором я писал в своем ответе I also fire validation for all rows when applied_amount is changed. Каждая форма ничего не знает о других - person yurzui; 13.02.2018
comment
Это значит, что вы что-то упустили. Проверьте это обновление ng-run.com/edit/Vhvk0iGIJEWI4OXeCcNW - person yurzui; 13.02.2018
comment
Привет. Я реализовал это в своем локальном проекте, и у него есть ошибка, называемая Expression, измененная после того, как она была проверена. Итак, я реализовал ссылку changeDetector, и ошибка исчезла. Но некоторые говорят, что changeetectorref не годится, так как это дорогая операция. - person Joseph; 17.02.2018
comment
Привет, ты там? - person Joseph; 17.02.2018
comment
Omg.. Я не знаю, почему мне нужно тратить столько времени на stackoverflow. Что не так с моим ответом? Если это не сработает, вы должны хотя бы предоставить репродукцию. ChangeDetectorRef можно использовать для исправления изменения выражения. - person yurzui; 18.02.2018
comment
Вот что я хотел услышать. спасибо юрзуй - person Joseph; 18.02.2018

Проблема с вашим кодом заключается в том, что вы передаете FormArray (строки) в валидатор, а не в группу.

Предлагаю переписать так:

initGroup() {
   let rows = this.reportForm.get('rows') as FormArray;
   rows.push(this.fb.group({
       expense_account: ['', Validators.required],
       description: ['', Validators.required],
       amount: ['', Validators.required],
   },{validator: this.customValidator})) // it will automatically be applied to the group
}
person Boris Lobanov    schedule 12.02.2018
comment
Я думаю, что у меня проблема с customValidator. Он говорит, что не может прочитать родителя неопределенного. Мне нужно проверить, больше ли сумма, чем apply_amount. Сумма находится внутри строк, а apply_amount — вне строк. - person Joseph; 13.02.2018