数据未从Angular中的组件传递

时间:2019-11-23 01:05:34

标签: javascript html angular

我正在尝试使用@Input方法在组件之间传递数据。出于某种原因,我在控制台中没有任何错误,但是在试图将数据从 content 传递到 header (即Header组件)的组件中没有任何显示。我有一个由以下3个组件构成的主视图组件:

HOME-VIEW

  • HEADER
  • 内容

数据需要从内容组件传递到头组件。到目前为止,我正在使用@Input方法,但是它不起作用。

Header.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { faHeadphones} from '@fortawesome/free-solid-svg-icons';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {

  faHeadphones = faHeadphones;

  @Input()playlist= [];

  constructor() { }

  ngOnInit() {
  }
}

header.html

<nav class="navbar navbar-dark bg-dark">
  <div class="container">
    <a class="navbar-brand" href="#">
      <fa-icon [icon]="faHeadphones"></fa-icon>
      Navbar
    </a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
      aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav">
        <li class="nav-item active">
          <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Search</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">About</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="#">{{playlist.length}}</a>
          </li>
      </ul>
    </div>
  </div>
</nav>

content-component.ts

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../../services/api.service';
import { FormGroup, FormControl } from '@angular/forms';
import { FormBuilder } from '@angular/forms';
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import { faRedo } from '@fortawesome/free-solid-svg-icons';
import { faHeadphones } from '@fortawesome/free-solid-svg-icons';
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
import { faPlus } from '@fortawesome/free-solid-svg-icons';

@Component({
  selector: 'app-content',
  templateUrl: './content.component.html',
  styleUrls: ['./content.component.scss']
})
export class ContentComponent {

  public data = [];
  public playlist = [];
  public apiData: any;
  public results = [];
  public loading = false;
  public noData: any;
  p: number = 1;
  faSearch = faSearch;
  faRedo = faRedo;
  faHeadphones = faHeadphones;
  faExternalLinkAlt = faExternalLinkAlt;
  faPlus = faPlus;

  searchQuery: string = "";
  clickMessage = '';

  constructor(private service: ApiService) { }

  getAll() {
    this.service.getAll(this.searchQuery).subscribe((results) => {
      this.loading = true;
      console.log('Data is received - Result - ', results);
      this.data = results.results;
      this.loading = false;

      if (this.data.length <= 0) {
        this.noData = true;
      } else if (this.data.length >= 1) {
        this.noData = false;
      } else {
        this.noData = false;
      }
    })
  }

  closeAlert() {
    this.noData = false;
  }

  addSongToPlaylist(itunes) {
    this.playlist.push(itunes);
    console.log('Playlist - ', this.playlist);
}

  refresh(): void {
    window.location.reload();
  }

  Search() {
    this.service.getAll(this.searchQuery).subscribe((results) => {
      this.loading = true;
      console.log('Data is received - Result - ', results);
      this.data = results.results;
      this.loading = false;
    })
  }
  ngOnInit() {

  }
}

主视图component.html

<app-header [playlist]="playlist"></app-header>
    <app-content ></app-content>
<app-footer></app-footer>

home-view.ts

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../services/api.service';

@Component({
  selector: 'app-home-view',
  templateUrl: './home-view.component.html',
  styleUrls: ['./home-view.component.scss']
})
export class HomeViewComponent implements OnInit {

  public playlist = [];

  constructor(private service: ApiService) { }

  ngOnInit() {
  }

}

3 个答案:

答案 0 :(得分:0)

如果我很好理解,那三个组件共享同一数组(称为播放列表)。事实是,播放列表正在ContentComponent内部进行修改,并且

  1. 您没有将此更改通知父级(HomeViewComponent),
  2. Content和Header组件是同级组件,因此,它们无法通过简单的绑定进行通信。

您有两个选择:

  1. 将播放列表逻辑移动到父组件,并通过ContentComponent内的@Output装饰器触发这些父操作,或者
  2. 对ContentComponent内部的播放列表使用双向绑定

如果选择第二个选项,则每次声明ContentComponent内的数组时,都可以声明一个{Output {@ 1}}之类的@Output属性,并调用@Output() playlistChange = new EventEmitter(),也可以在模板中更改{{1} }与this.playlistChange.emit(this.playlist)

也不要忘记声明<app-content></app-content>之类的输入属性

注意:为了使用双向绑定,Output属性必须按照我指定的名称命名,也就是说,如果您的属性名为 x ,则output属性必须被命名为 x 更改

答案 1 :(得分:0)

app-content组件中,添加事件发射器

...
@Output() playlistChange: EventEmitter = new EventEmitter<any>();
...

并在addSongToPlaylist内发出播放列表

...
addSongToPlaylist(itunes) {
    this.playlist.push(itunes);
    this.playlistChange.emit(this.playlist);
    console.log('Playlist - ', this.playlist);
}
...

现在,将app-content标记更改为home-view.html中的以下代码

...
<app-content (playlistChange)="assignVal($event)"></app-content>
...

在home-view.component中添加AssignVal方法。

    assignVal(value){
    this.playlist = value;
}

答案 2 :(得分:0)

我发现最简单的方法是创建服务并将其传递到组件的constructor中:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PlaylistService {

  public playlist = [];

  constructor() { 

  }
}