Угловое получение значения идентификатора ссылки в ngFor

#.net #angular #reference #ngfor

Вопрос:

В настоящее время я работаю над личным проектом с Angular и .NET API с SQL Server для серверной части. Теперь я не хотел использовать внешние ключи, потому что тогда вы зависите от базы данных. Таким образом, в моих моделях есть идентификаторы, на которые ссылаются другие объекты.

Основная цель приложения-создание списка задач, в котором указывается, выполнена ли задача и кому она поручена. Таким образом, модель задачи имеет атрибут с именем: «responsible_user_id»: 1, например. Число 1 означает, что пользователь с идентификатором = 1 отвечает за эту задачу. Но 1 мало что значит на интерфейсе, я хочу показать имя пользователя.

Теперь у меня есть следующее:

 <div class="container">
    <div class="row" >
      <div class="col-4" *ngFor="let task of categoryTasks">
        <div class="card" style="width: 18rem;">
          <div class="card-body">
            <h5 class="card-title">{{task.item_title}} </h5>
    ----->>>  <h5 class="card-title">Reponsible user: {{task.responsible_user_id}} </h5>
            <h5 *ngIf="(task.item_status)"> <i  style="color:rgb(34, 216, 34);" class="bi bi-check-circle"></i>
            </h5>
            <h5 *ngIf="(!task.item_status)"> <i style="color:red;" class="bi bi-x"></i>
            </h5>
              <br>
            <button (click)="setDone(task.item_id)"  class="btn btn-primary">Done</button>
        </div>
      </div>
      </div>
    </div>
  </div>
 

Я разместил стрелки в строке, где я хочу, чтобы отображалось имя пользователя. В настоящее время я могу показать только идентификатор, но для получения указанного пользователя необходим еще один новый вызов API. Все, что я пробовал, приводило к множеству ошибок, пока программа не вышла из строя.

Метод, который я пробовал, создавал метод в файле component.ts:

   public GetResponsibleUser(id){
    var user:any;

    this.userService.getUser(id).pipe(first())
    .subscribe(res => user = res);

    var name = user.username;

    return name;
  }
 

который я бы назвал из строки выше со стрелками перед ним, но это не сработало.

Есть ли кто-нибудь, кто знает, как решить эту проблему?

Заранее спасибо!!

С уважением, Джулиус

Ответ №1:

Ваша функция GetResponsibleUser работает не так, как это, так как вам пришлось бы возвращать наблюдаемое:

 NOT-WORKING!
    public GetResponsibleUser(id): Obserable<User> {
        return this.userService.getUser(id).pipe(first())
    }
 

И в HTML вам нужно будет добавить асинхронный канал:

   <h5 class="card-title">Reponsible user: {{GetResponsibleUser(task.responsible_user_id) | async }}</h5>
 

Но это все равно приведет к огромному количеству вызовов на серверную часть, так как каждый раз, когда вызывается obserable (вызов завершен), обнаружение изменений angulars будет выполняться и создаст следующий вызов этого метода. -> Заканчивается бесконечным звонком.

Вы могли бы создать своего рода кэш в своем компоненте или даже лучше в a Service .
Просто в качестве примера:

   private cache = new Map<string, string>();

  GetResponsibleUser(userId: string): Observable<string> {
    if (this.cache.get(userId)) {
      return of(this.cache.get(userId));
    } else {
      return this.userService.getUser(userId)
        .pipe(
          first(),
          map(user => user.getUsername()),
          tap(username => this.cache.set(userId, username))
        );
    }
  }
 

Ответ №2:

***Не делайте этого!!! Это неправильно:

 getUsersName(id) {
   return this.usersService.getUser().pipe(
     map(user => user.Name)
   )
}
 

и в шаблоне:

  {{ getUsersName(user.id) }}
 

Если вы поставите наблюдаемых из HTTP-запроса в шаблон с помощью асинхронных трубы — приложение будет делать 7 запросов для каждого изменения детектор итерации и ответы будут изменения данных и пожарной изменить детектора -> детектор обновления данных и труб пожара -> асинхронный трубопроводов(подписывается) потоки и огонь детектор снова , потому что Нг зоне позвонить детектора, когда HTTP-запрос случилось цикла!!!**

Если вы не можете добавить поле «Имя» для списка пользователей, см. Пример работы:
stackblitz-пример с пользователями и их сообщениями в ваших именах обращений

**почему .pipe(first()) не поможет ? — потому что приложение будет создавать новый поток с первым каналом каждый раз, когда вызывается метод, возвращающий поток. Таким образом, он работает только для потоков, возвращающих данные в нескольких итерациях. Также его можно использовать для потоков с одной итерацией — для отмены подписки на поток после ответа, — но если ответ будет слишком длинным, вы можете оставить компонент, а обратный вызов подписки может быть попыткой использовать несуществующие свойства умершего компонента.