Angular Сравнивает объекты по ссылке по умолчанию
Вы почти там. Проблема в том, что ваш select
получает список option
с ссылкой на Post
s как часть ngFor
. Теперь, чтобы узнать, какой option
выбран в данный момент, Angular сравнивает каждый объект post
с текущим значением selectedPost$ | async
.
По умолчанию используется оператор ===
. Оператор ===
сравнивает примитивы по значению, но объекты по ссылке. Пример:
console.log('a' === 'a');
const obj = {'a': 'b'};
const obj2 = obj;
console.log(obj === obj2);
console.log(obj === {'a': 'b'});
Таким образом, чтобы post
считался тем же постом, что и selectedPost$ | async
, они должны быть фактически тем же объектом, а не просто объектом, который выглядит то же самое.
Вы фактически получаете несколько копий одного и того же сообщения, а не только одно сообщение
Теперь это не так: поскольку вы используете async
В случае обнаружения изменений сообщения перезагружаются из API. Когда вы просматриваете вкладку сети вашего браузера, вы можете увидеть, что есть три запроса:
Полезная нагрузка ответа на все запросы одинакова, но поскольку объекты Post
возвращаются три раза, они сохраняются в памяти три раза. JavaScript не может знать, что они на самом деле одинаковы, и сравнение ===
возвращает false
.
Решение: предоставьте свою compareWith
функцию
Как вы можете решить это? Вы можете Angular правильно сравнить Post
объектов в вашем select
. Вам просто нужно задать себе вопрос: откуда мне знать, что два Post
объекта на самом деле являются одним и тем же объектом? В данном случае ответ таков: когда они имеют одинаковый идентификатор.
Теперь вы можете написать свою собственную инструкцию для Angular для сравнения объектов или выбора: просто добавьте ввод compareWith
в выбор :
<select [ngModel]="selectedPost$ | async"
(change)="onSelected($event.target.value)"
[compareWith]="comparePosts"
>
Теперь Angular знает, как использовать метод с именем comparePosts
для сравнения двух сообщений. Теперь, как этот метод может выглядеть? Например, вот так:
comparePosts(p1: Post, p2: Post) {
return p1.id === p2.id;
}
Теперь Angular знает, как правильно сравнить два Post
объекта, и ваша проблема решена.
PS: Пожалуйста, не забудьте написать лучше comparePosts
метод, чем я, например, также правильно обрабатывает undefined
и null
значения.