HTML, похоже, пытается отобразить переменную до того, как она будет инициализирована в Angular

Приложение работает нормально, но консоль, кажется, отображает эту ошибку каждый раз, когда я обновляюсь:

ПОЛУЧИТЬ http://localhost:4200/[object%20Object] 404 (не найдено) @ lists.component.html:3 (кажется, ссылается на 3-ю строку html-кода ниже)

Я полагаю, что HTML пытается отобразить переменную l.image до того, как она будет правильно инициализирована с помощью запроса GET из локального SQL?

Мое приложение по существу использует Angular для запроса JS-сервера node, который возвращает результат SQL-запроса. Заранее спасибо.

Угловой код

export class ListsComponent implements OnInit {

  lists:any

  constructor(private http: HttpClient, private router: Router, private cloud: Cloud, private sanitizer: DomSanitizer) {
    this.getImages()
   }

  ngOnInit() {
  }

  async getImages(){
    this.lists = await this.http.get<any>('/lists').toPromise()
  }

JS-код узла

app.get('/lists', async (req, resp) => {
    const conn = await pool.getConnection()
    try {
        const [ result, _ ] = await conn.query(SQL_SELECT_ALL_FROM_LISTS)

        resp.status(200)
        resp.type('application/json').send(result)
    } catch(e) {
        console.error('ERROR: ', e)
        resp.status(500)
        resp.end()
    } finally {
        conn.release()
    }
})

HTML

    <li *ngFor = "let l of lists" class = "list-group-item d-flex justify-content-between align-items-center">

        <img *ngIf = "l.image !== 'undefined'" [src] = "l.image" class = "img-thumbnail img-fluid" width = "10%">
        
        <a (click) = "routeToTasks(l.listID, l.listName)" class = "list-group-item list-group-item-action list-group-item-primary">{{l.listName}}</a>
        <button type = "button" class = "btn btn-danger" (click) = "deleteList(l.listID)">Delete</button>    
    </li>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
456
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Две вещи, которые вы можете сделать. Вместо вызова this.getImages() из constructor вызовите его из ngOnInit и заверните li внутрь ng-content

 <ng-content *ngIf = "list">
      <li  *ngFor = "let l of lists"
        class = "list-group-item d-flex justify-content-between align-items-center">
        <img *ngIf = "l.image !== 'undefined'" [src] = "l.image" class =
        "img-thumbnail img-fluid" width = "10%" > 
        <a (click) =
        "routeToTasks(l.listID, l.listName)" class = "list-group-item
        list-group-item-action list-group-item-primary"> {{l.listName}} </a> 
        <button type = "button" class = "btn btn-danger" (click) =
        "deleteList(l.listID)"> Delete </button> </li> </ng-content>
      </li>
</ng-content>

Вы визуализируете <li *ngFor = "let l of lists" >, однако lists не определено в начале.

Я бы посоветовал либо указать lists:any = [], чтобы было начальное значение, и оно не отображало никаких дочерних объектов, либо вы могли бы использовать канал async, который будет обрабатывать ожидание динамических данных:

<li *ngFor = "let l of lists | async" >

и удалите функцию toPromise()from you

async getImages(){
    this.lists = await this.http.get<any>('/lists')
  }

Поскольку вы используете Angular, подумайте об использовании Observable

В вашем коде это можно изменить на


export class ListsComponent implements OnInit {
  lists:any[] = []; // Create an empty list

  constructor(private http: HttpClient, private router: Router, private cloud: Cloud, private sanitizer: DomSanitizer) {
   }

  ngOnInit() {
    this.getImages.subscribe(lists => this.lists = lists)
  }

  getImages = () => this.http.get<any[]>('/lists')
  
}

Обратите внимание на изменения;

  1. Изменено lists:any на lists:any[], так как мы ожидаем массив

  2. заменил getImages() на getImages = () => this.http.get<any[]>('/lists'). Это функция, которая возвращает Observable

  3. Вместо использования async/await мы просто используем subscribe

Ответ принят как подходящий

Попробуйте использовать вопросительный знак непосредственно перед использованием оператора точки, как показано ниже:

<li *ngFor = "let l of lists" class = "list-group-item d-flex justify-content-between align-items-center">
    <img *ngIf = "l?.image !== 'undefined'" [src] = "l?.image" class = "img-thumbnail img-fluid" width = "10%">
    <a (click) = "routeToTasks(l.listID, l.listName)" class = "list-group-item list-group-item-action list-group-item-primary">{{l.listName}}</a>
    <button type = "button" class = "btn btn-danger" (click) = "deleteList(l.listID)">Delete</button>    
</li>

Я бы предложил добавить директиву ngIf в ваш html-компонент и сделать значение истинным, как только вы получите ответ с сервера.

<div *ngIf = "displayDetails">

<li *ngFor = "let l of lists" 
...

</div>


 

В вашем компоненте, как только вы получите ответ от сервера, сделайте детали отображения истинными.

 displayDetails:boolean = false;

     this.getImages.subscribe(lists => {
    this.lists = lists ;
      this.displayDetails = true;
    )}

   

Другие вопросы по теме