Как ждать загрузки данных из API и затем выполнить другое действие в пользовательском интерфейсе? - PullRequest
1 голос
/ 27 сентября 2019

У меня есть метод, который получает список пользователей из API и заполняет компонент списка.Теперь я хочу выделить первый элемент списка после загрузки списка из API.Я попробовал следующий подход, и он отлично работает с setTimeout, но как я могу сделать это без функции setTimeout

Вот код, который я попробовал,

public getUserList(){ 
    return this.http.get('https://jsonplaceholder.typicode.com/users').pipe(tap(x => {
      this.lists = x;
    }))
    .subscribe((data) => {
      setTimeout(() => { 
        this.clickFirstList();
      }, 1000);
    });
  }

clickFirstList() {
    Array.from(this.ulElement.nativeElement.children).forEach((element: HTMLElement, index: number) => {
      if (index === 0) {
        console.log(element);
        element.click();
      }
    });
}

Вот рабочаякод на стекблице.https://stackblitz.com/edit/angular-brpz2j?file=src/app/search-list.component.ts

Ответы [ 4 ]

1 голос
/ 27 сентября 2019

Вы не должны так манипулировать DOM, в этом нет необходимости.Мы используем угловые привязки, и, используя их, мы также можем значительно сократить код, который вы используете в данный момент.Поэтому удалите все эти манипуляции с DOM.

Прежде всего мы можем опустить вызов lists для родительского или дочернего элемента.Теперь вы выполняете запрос get дважды, что на самом деле не имеет смысла.Я держу запрос на получение у ребенка.Мы также можем сделать запрос в OnInit, зачем нам это нужно делать в AfterViewInit?

ngOnInit() {
  this.getUserList();
}

public getUserList() {
  return this.http
     // DONT USE 'ANY', type your data using interface or class
    .get<any[]>("https://jsonplaceholder.typicode.com/users")
    .subscribe(data => {
      this.lists = data;
      // you want to emit initially the first item to parent via output
      // do it here.
      this.onClickList(0, this.lists[0] || {})
    });
 }

Также мы вводим новую переменную selectedIndex, которую мы будем изменять в зависимости от выбранного элемента.Как Дженс сделал в своем ответе.Вы хотите, чтобы первый элемент был активен изначально, мы передаем 0 в качестве индекса функции onClick:

public onClickList(i: number, item: any) {
  this.selectedIndex = i
  this.selectedList.emit(Object.assign({}, item));
}

Мы добавляем это в шаблон следующим образом:

<ng-container *ngFor="let item of lists | filter: searchText; index as i">
  <li [class.active]="i === selectedIndex"
    (click)="onClickList(i, list)">
    {{ list.name }}
  </li>
</ng-container>

Ваш разветвленный STACKBLITZ

Как упомянуто как комментарий внутри кода.НЕ ИСПОЛЬЗУЙТЕ any, он полностью отрицает цель Введите Script, поэтому вводите свои данные либо с помощью интерфейсов, либо с помощью классов.Я предпочитаю интерфейсы.

0 голосов
/ 27 сентября 2019

Tap также принимает карту объектов для регистрации следующего, ошибки и завершения

  public getUserList(){ 
    return this.http.get('https://jsonplaceholder.typicode.com/users')
    .pipe(
       tap( {
         next: x => {
           console.log('on next', x);
         },
         error: error => {
           console.log('on error', error.message);
         },
         complete: () => {
           console.log('on complete')
           this.clickFirstList()
         }
       }))
       .subscribe((x) => {
        console.log(x)
       });
  }
0 голосов
/ 27 сентября 2019

Вы можете использовать следующий код

public getUserList(){ 
    return this.http.get('https://jsonplaceholder.typicode.com/users').pipe(tap(x => {
      this.lists = x;
    }))
    .subscribe((data) => {
    },
    (err) => {
        // code to execute if request fails
    },
    () => {
    this.clickFirstList();
    }
  });
}
0 голосов
/ 27 сентября 2019

Я бы удалил clickFirstList.И используйте css и angular.

Я не знаю, какой элемент html вы зациклили, но скажем, его список, например: html

<ul>
  <li *ngFor="let user of list:let index = index" [class.selected]="index===selectedIndex" (click)="onClick(index)> 
    {{user.Name}}
  </li>
</ul>

и css

.selected{
   background-color: yellow;
}

и в машинописном компоненте:

selectedIndex = 0; //Default value. 
onClick(index:number){
   this.selectedIndex=index;
}  
...