Angular: Сравнить предыдущие значения с выходным эмиттером и ValueChanges - PullRequest
2 голосов
/ 10 марта 2020

У нас есть Angular дочерняя форма, передающая значения с помощью Valuechanges. В родительском компоненте мы хотим запускать задачи, если новое значение почтового индекса от child отличается от предыдущего значения почтового индекса.

Сейчас мы создаем переменную для хранения предыдущих почтовых индексов.

Есть ли более чистый способ сделать это с помощью Output? Я знаю NgOnchanges для ввода, мы можем отслеживать предыдущие изменения с помощью change.previousValue.

Интересно, если изменения выходного значения имеют что-то похожее?

Дочерняя форма:

public addressSub = new Subscription();
public editAddressForm: FormGroup;
@Output addressFormChange = new EventEmitter<any>();

this.addressSub.add(this.editAddressForm.valueChanges.subscribe(data=> {
    this.addressFormChange.emit(this.editAddressForm);
})))

Родительский компонент:

В Parent он подписывается как.

public addressFormChangeEvent(addressFormEvent){
    this.addressMailingForm = addressFormEvent;
    if (this.addressMailingForm.get('zipCode') != previousZipCode) {
         doSomethingetc();
    }
    previousZipCode = this.addressMailingForm.get('zipCode');
}

Имеет ли Angular что-нибудь в библиотеке для просмотра предыдущих значений с помощью подписки ValueChanges?

Ответы [ 3 ]

5 голосов
/ 20 марта 2020

IMO гораздо проще сделать это с помощью попарно и startWith .
Кроме того, вы можете передать форму от родительского компонента к дочернему и подписаться на родительский компонент, например:

form.valueChanges
    .pipe(startWith(undefined), pairwise())
    .subscribe(valuesArray => {
         const newVal = valuesArray[1];
         const oldVal = valuesArray[0];
         if (newVal !== oldVal) {
             // do your thing
         }
    })
1 голос
/ 19 марта 2020

Лично я бы предпочел rxjs, а именно: BehaviorSubject, ReplaySubject и AsyncSubject, а не EventEmitter, чтобы обмениваться данными между компонентами в Angular. Для больших проектов Redux , конечно, еще один вариант. Глядя на вашу ситуацию, было бы неплохо использовать ReplaySubject, поскольку он может отправлять «старые» значения новым подписчикам.

ReplaySubject:

ReplaySubject сопоставим с поведением субъекта в том, что он может отправлять «старые» значения новым подписчикам. Однако у него есть дополнительная характеристика c, позволяющая записывать часть наблюдаемого выполнения и, следовательно, сохранять несколько старых значений и «воспроизводить» их новым подписчикам.

При создании объекта ReplaySubject вы можете указать, сколько значений Вы хотите хранить и как долго вы хотите хранить их. Другими словами, вы можете указать: «Я хочу сохранить последние 5 значений, которые были выполнены за последнюю секунду до новой подписки». Смотрите пример кода ниже:

replaySubject. js:

import * as Rx from "rxjs";

const subject = new Rx.ReplaySubject(2);

// subscriber 1
subject.subscribe((data) => {
    console.log('Subscriber A:', data);
});

subject.next(Math.random())
subject.next(Math.random())
subject.next(Math.random())

// subscriber 2
subject.subscribe((data) => {
    console.log('Subscriber B:', data);
});

subject.next(Math.random());

// Subscriber A: 0.3541746356538569
// Subscriber A: 0.12137498878080955
// Subscriber A: 0.531935186034298
// Subscriber B: 0.12137498878080955
// Subscriber B: 0.531935186034298
// Subscriber A: 0.6664809293975393
// Subscriber B: 0.6664809293975393

Как упоминалось ранее, вы также можете указать, как долго вы хотите сохранять значения в теме воспроизведения.

replaySubject-2. js:

import * as Rx from "rxjs";

const subject = new Rx.ReplaySubject(2, 100);

// subscriber 1
subject.subscribe((data) => {
    console.log('Subscriber A:', data);
});

setInterval(() => subject.next(Math.random()), 200);

// subscriber 2
setTimeout(() => {
  subject.subscribe((data) => {
    console.log('Subscriber B:', data);
  });
}, 1000)

// Subscriber A: 0.44524184251927656
// Subscriber A: 0.5802631630066313
// Subscriber A: 0.9792165506699135
// Subscriber A: 0.3239616040117268
// Subscriber A: 0.6845077617520203
// Subscriber B: 0.6845077617520203
// Subscriber A: 0.41269171141525707
// Subscriber B: 0.41269171141525707
// Subscriber A: 0.8211466186035139
// Subscriber B: 0.8211466186035139

Для получения более подробной информации смотрите Понимание rx js BehaviorSubject, ReplaySubject и AsyncSubject . Надеюсь, это поможет ...

1 голос
/ 16 марта 2020

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

Первое улучшение

Мы будем использовать два прослушивателя формы:

  • valueChanges: прослушивает изменения значения формы. Выдает каждое изменение, например: когда вы набираете в почтовом индексе ввод '1' ... '15' ... '150' ... каждая новая буква будет новым событием emit
  • statusChanges: прослушивает статус формы. Таким образом, мы знаем, является ли форма (и почтовый индекс) действительной или недействительной.

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

Например, события вывода компонента

Я буду включать почтовые индексы только в данные примеров, которые действительны при длине 5.

  • ДО: [1, 15, 150, 1510, 15109, 2, 28, 286, 2860, 28600, 2, 28, 286, 2860, 28600, 7, 74, 746, 7462, 74625, 7, 74, 746, 7462, 74625]
  • ПОСЛЕ: [15109, 28600, 28600, 74625, 74625]

Второе улучшение

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

Для этого мы будем использовать rx js distinctUntilChanged

combineLatest([
  this.editAddressForm.statusChanges,
  this.editAddressForm.valueChanges,
]).pipe(
  filter(()=> this.editAddressForm.valid)
  map([status, value] => value),
  distinctUntilChanged()
)
.subscribe(value => {
  this.addressFormChange.emit(value);
});

Это должно выдавать только не дублированные значения:)

Например, события вывода компонента

  • ДО: [1, 15, 150, 1510, 15109, 2, 28, 286, 2860, 28600, 2, 28, 286, 2860, 28600, 7, 74, 746, 7462, 74625, 7, 74, 746, 7462, 74625]
  • ПОСЛЕ: [15109, 28600, 74625]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...