Açısal: Hangi yaşam döngüsü kancasının Bileşen için giriş verilerinin mevcut olduğu


86

Veri imageolarak nesneler dizisini alan bir bileşenim var Input.

export class ImageGalleryComponent {
  @Input() images: Image[];
  selectedImage: Image;
}

Bileşen yüklendiğinde selectedImagedeğerin imagesdizinin ilk nesnesine ayarlanmasını isterim . Bunu OnInityaşam döngüsü kancasında şu şekilde yapmaya çalıştım :

export class ImageGalleryComponent implements OnInit {
  @Input() images: Image[];
  selectedImage: Image;
  ngOnInit() {
    this.selectedImage = this.images[0];
  }
}

bu bana bir hata veriyor , bu Cannot read property '0' of undefinedda imagesdeğerin bu aşamada ayarlanmadığı anlamına geliyor . OnChangesKancayı da denedim ama takılı kaldım çünkü bir dizideki değişiklikleri nasıl gözlemleyeceğime dair bilgi alamıyorum. Beklenen sonuca nasıl ulaşabilirim?

Ana bileşen şuna benzer:

@Component({
  selector: 'profile-detail',
  templateUrl: '...',
  styleUrls: [...],
  directives: [ImageGalleryComponent]
})

export class ProfileDetailComponent implements OnInit {
  profile: Profile;
  errorMessage: string;
  images: Image[];
  constructor(private profileService: ProfileService, private   routeParams: RouteParams){}

  ngOnInit() {
    this.getProfile();
  }

  getProfile() {
    let profileId = this.routeParams.get('id');
    this.profileService.getProfile(profileId).subscribe(
    profile => {
     this.profile = profile;
     this.images = profile.images;
     for (var album of profile.albums) {
       this.images = this.images.concat(album.images);
     }
    }, error => this.errorMessage = <any>error
   );
 }
}

Üst bileşenin şablonunda buna sahiptir

...
<image-gallery [images]="images"></image-gallery>
...

1
imagesVeriler üst bileşende nasıl doldurulur? Yani, bir http istek (leri) aracılığıyla mı? Öyleyse, ImageGalleryComponent'in http gözlemlenebilir'e abone olması () daha iyi olabilir.
Mark Rajcok

@MarkRajcok images, ebeveyn tarafından bu şekilde kullanılan verilerin sadece bir parçası, yani {profile: {firstName: "abc", lastName: "xyz", images: [ ... ]}}çocuğa abone olursam, yine de ebeveyn için abone olmam gerekecek ve tekrardan kaçınmak istiyorum
Optimus Pette

Alt bileşen oluşturulduğunda üst bileşendeki images dizisi doldurulursa, ngOnInit () çağrılmadan önce images input özelliği doldurulmalıdır. Herhangi birinin size daha fazla yardımcı olması için (veya sorunu gösteren minimal bir Plunker oluşturması için) images dizisinin ana bileşende nasıl yerleştirildiği hakkında daha fazla bilgi sağlamanız gerekir.
Mark Rajcok

@MarkRajcok Ana bileşeni ve resimlerin içine nasıl yerleştirildiğini ekledim.
Optimus Pette

2
Öyleyse evet, üst bileşeniniz images özelliğini doldurmak için http kullanıyor (çünkü bir hizmet kullanıyor) görünüyor. Bu eşzamansız bir işlem olduğundan, alt bileşenin input özelliği, ngOnInit () yöntemi çağrıldığında doldurulmayacaktır. Kodunuzu ngOnInit () 'den ngOnChanges ()' e taşıyın ve çalışmalıdır.
Mark Rajcok

Yanıtlar:


89

Girdi özellikleri ngOnInit()çağrılmadan önce doldurulur . Ancak bu, girdi özelliğini besleyen üst mülkün alt bileşen oluşturulduğunda zaten doldurulmuş olduğunu varsayar.

Senaryonuzda durum böyle değil - görüntü verileri bir hizmetten eşzamansız olarak dolduruluyor (dolayısıyla bir http isteği). Bu nedenle, giriş özelliği ngOnInit()çağrıldığında doldurulmayacaktır .

Sorununuzu çözmek için, veriler sunucudan döndürüldüğünde, üst özelliğe yeni bir dizi atayın. Uygulamak ngOnChanges()çocukta. ngOnChanges()Açısal değişiklik tespiti yeni dizi değerini alt öğeye yaydığında çağrılır.


1
Size katılıyorum çünkü ben de aynı problemle karşılaştım. ngOnchanges()Çocuğa uyguladıktan sonra bile hata Cannot read property '0' of undefinedgeliyor. Ancak uygulama sorunsuz bir şekilde devam edebilir. Bu hata, başlangıçta input özelliğinin doldurulmaması nedeniyle ortaya çıkar. Zaman ngOnChanges()uyumsuz aramadan alınan verilerin ikinci kez çağrılmasıyla doldurulur . Benim durumum için, bu çözüme ek olarak, html'de boş operatörüne karşı korumayı ekledim . Hatayı açıkça çözdü.
Thilina Samiddhi

7

Ayrıca görüntüleriniz için değer değiştiğinde çağrılacak bir ayarlayıcı ekleyebilir ve ayarlayıcının kendisinde varsayılan seçili görüntünüzü ayarlayabilirsiniz:

export class ImageGalleryComponent {
  private _images: Image[];

  @Input()
  set images(value: Image[]) {
      if (value) { //null check
          this._images = value;
          this.selectedImage = value[0]; //setting default selected image
      }
  }
  get images(): Image[] {
      return this._images;
  }

  selectedImage: Image;
}

1

Birkaç şeyi değiştirerek çözebilirsiniz.

  export class ImageGalleryComponent implements OnInit {

  @Input() images: Image[];
  selectedImage: Image;

  ngOnChanges() {
      if(this.images) {
        this.selectedImage = this.images[0];
      }
  }

 }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.