Измените цвет кнопки, когда вам нравится сообщение, используя SignalR

#angular #typescript #signalr #ng-class #signalr.client

Вопрос:

Я создал приложение со списком сообщений, и пользователю может понравиться/не понравиться сообщение. Для функции «Нравится» я использовал SignalR, и все работает нормально, но я хочу изменить цвет кнопки «Нравится», если зарегистрированному пользователю уже понравилось сообщение, чтобы он знал, какие сообщения ему понравились. Если пользователю не понравился пост, кнопка «Нравится» будет серой, в противном случае она будет оранжевой. Я пытался сделать это так, используя ngClass на основе логического isActive:

 <button (click)="liked(post)" class="btn liked mr-5">Like <em [ngClass]="[isActive ? 'my-color' : 'active-color']" class="fa fa-thumbs-up"></em> {{post?.likes.length}}</button>
 
 .my-color {
  color: grey;
}

.active-color {
  color: #e08e23;
}

 
 export class PostCardComponent implements OnInit, OnDestroy {

  @Input() post: Post;
  isActive = false;

 constructor(private postService: PostsService) {}

 ngOnInit(): void {
    this.postLiked();

    this.likesSubscription = this.postService.likeMessageReceive.subscribe(result =>{
      
        if ( result.postId ===  this.post.id) {
            this.post = result.numOfLikes;
        }
  })

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

postLiked() {
    const user: User = JSON.parse(localStorage.getItem('user'));
    const id = this.getDecodedToken(user.token).nameid;
    var checkLike = this.post.likes.filter(like => (like.userId === parseInt(id)));
    console.log(checkLike);
    if(checkLike.length === 0) {
      this.isActive = true;
    }
    return this.isActive;
  }

  liked(post: Post) {
    const user: User = JSON.parse(localStorage.getItem('user'));
    const id = this.getDecodedToken(user.token).nameid;
    
    this.postService.setLike(parseInt(id), post.id)
    .then(() => {
      this.postLiked();
    });
  }
}
 

Аналогичная функциональность, созданная с помощью SignalR, выглядит следующим образом:

  private hubConnection: HubConnection;
 likeMessageReceive: EventEmitter<{ numOfLikes: Post, postId: number, userId: number }> = new EventEmitter<{ numOfLikes:Post, postId: number, userId: number }>();


 connectHubs(user: User) { 
      this.hubConnection = new HubConnectionBuilder()
      .withUrl(this.hubUrl   'like', { accessTokenFactory: () => user.token, 
      skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets })
      .build();
  
      return  this.hubConnection.start()
                 .then(() => {
                     this.hubConnection.on('ReceiveMessage', (numOfLikes, postId, userId) => {
                      user.id = userId;
                       this.likeMessageReceive.emit({ numOfLikes, postId, userId });
                     });
                 })
                 .catch(error => console.log(error)); 
  }
  
  setLike(userId: number, postId: number) {
     return this.hubConnection.invoke('SetLike', userId, postId);
  }
 

Бэкэнд:

 
        public async Task SetLike(int userId, int postId)
        {
            Like l = new Like();

            Like temp = _context.Likes.Where(x => x.PostId == postId amp;amp; x.UserId == userId).FirstOrDefault();

            if(temp != null)
            {
                _context.Likes.Remove(temp);
            } else
            {

                l.UserId = userId;
                l.PostId = postId; 

                _context.Likes.Add(l);

            }

            await _context.SaveChangesAsync();

            var post = await _postRepository.GetPostAsync(postId);

            await Clients.All.SendAsync("ReceiveMessage", post, postId, userId);

        }
 

Когда я не подписываюсь на сообщение, кнопка мгновенно меняется с оранжевой на серую и работает по желанию. Однако, наоборот, если мне нравится сообщение, кнопка становится серой на оранжевую только после обновления страницы, а не мгновенно. Это почему?

Комментарии:

1. Как checkLike isActive выглядит / журнал? В любом случае, я предполагаю, что обертывание this.postLiked(); с помощью NgZone поможет, так как обратный вызов после setLike того, как обещание будет выполнено, может не быть принят Angular для обнаружения изменений. Если isActive журналы is обновляются каждый раз с false помощью, true ,…, но при печати пользовательского {{ isActive }} интерфейса они не будут синхронизированы, попробуйте NgZone.

2. isActive либо возвращает true/false, и checkLike выглядит так [] , если текущему пользователю не понравился пост, и что-то в этом роде, если ему/ей понравилось [info about user] . Но теперь я вижу, что галочка всегда пуста, даже если пользователю понравился пост, возможно, в этом и проблема. Я до сих пор не работал с NgZone, вы имеете в виду что-то подобное? this.ngZone.run(() => { this.postLiked(() => { isActive = ... }); }); Я думаю, что называю методы неправильными, но я не вижу проблемы.

3. Если это проблема с фактической установкой правильного значения isActive , то мы, вероятно, не сможем помочь без других подробностей. Хотя строка this.post.likes.length = result.numOfLikes; также выглядит неправильно, если likes только она не является массивом и length не является его длиной. Что касается NgZone, у вас был пример использования в документах. Так then(() => this.ngZone.run(() => this.postLiked())) .

4. Я понял проблему, но не знаю, почему это происходит. Когда я не люблю пост, все работает нормально, количество лайков уменьшается, а объект «Нравится» удаляется из базы данных. Однако, когда мне нравится пост, количество лайков увеличивается, но лайк не задается в базе данных, и я получаю пустой объект, подобный этому: (2) [{…}, empty] . Это почему? Я также опубликовал свой внутренний код.

5. Что меня также беспокоит, так это то, когда и как Вы добавляете лайки, которые Вы фильтруете. Потому что , если вы делаете это на хабе ReceiveMessage , может быть уже слишком поздно (после настройки isActive ). Вероятно isActive , тогда было бы лучше рассчитать likesSubscription setLike . Или просто установить this.isActive = false; , а не звонить this.postLiked() . Вы знаете, что это вы, кому все равно понравился пост, так зачем утруждать себя вычислением этого.