Rumah  >  Soal Jawab  >  teks badan

Sudut - Cara mengemas kini komponen kanak-kanak yang mengambil parameter input dan memaparkannya dengan betul pada kali pertama

Pengalaman pendidikan saya adalah seperti berikut:

<cdk-virtual-scroll-viewport itemSize="5" class="list-scroll">
         <app-education-item *ngFor="let education of loadedEducations"
          (isSelected)="changeSelected(education)"
          [ngClass]="{ selected: education == loadedEducation }"
          [education]="education"
          (isRemoved)="removeEducation(education)"
        ></app-education-item>
      </cdk-virtual-scroll-viewport>

dan merupakan komponen berikut

<div [ngClass]="{ 'list-item-container-collapsed' : isCollapsed, 'list-item-container': !isCollapsed, 'unselected': !isActive, 'selected': isActive}" (click)="selectEducation()">
    <div class="top-items-container" style="display: flex;">
     <div class="item-text">
     <span class="txt-header">{{educationHeader}}</span>
     <p class="txt-date"> 
         <span>{{startDate}}</span> - 
         <span>{{endDate}}</span>
     </p>
 </div>
</div>

Mempunyai logik berikut untuk memaparkan data yang diperoleh daripada parameter:

export class EducationItemComponent implements OnInit {

  @Input()
  education: Education;
  isCollapsed = false;
  isActive = false;
  startDate: string;
  endDate: string;
  educationHeader: string;
  educationDescription: string;

  constructor() { }

  ngOnInit(): void {
    console.log(this.education);
    this.startDate = this.education.startDate != '' ? formatDate(this.education.startDate, 'MMM yyyy', 'en-US')
        : formatDate(new Date(), 'MM YYYY', 'en-US') ;
    this.endDate = this.education.endDate != 'present' ? this.endDate = formatDate(this.education.endDate, 'MMM yyyy', 'en-US')
        : this.education.endDate;
    this.educationHeader = this.education.degree == undefined || this.education.description == undefined ? ''
        : this.education.degree + ' at ' + this.education.school;

    if (!this.education.description.enUS && this.education.description.nlNL) {
      this.educationDescription = this.education.description.nlNL;
    } else if (this.education.description.enUS) {
      this.educationDescription = this.education.description.enUS;
    }
}

Saya menggunakan acara tersuai untuk mengendalikan kemas kini

@Output() updatedValue: EventEmitter<any> = new EventEmitter<string>();

  constructor() {}

  ngOnInit(): void {}

  fieldChanged(changes: SimpleChanges) {
    this.updatedValue.emit(changes);
  }

Kemudian saya mempunyai html berikut untuk memanipulasi data:

<div class="update-wrap">
        <div class="list-header">Update education</div>
        <div>
          <div class="col-sm-6 input-wrapper">
            <app-input-field
              label="Institution"
              [value]="loadedEducation.school"
              (updatedValue)="loadedEducation.school = $event"
            ></app-input-field>
          </div>
          <div class="col-sm-6 input-wrapper date-picker-input">
            <app-input-field
              label="Degree"
              [value]="loadedEducation.degree"
              (updatedValue)="loadedEducation.degree = $event"
            ></app-input-field>
          </div>
        </div>
</div>

Walau bagaimanapun, data yang dikemas kini dalam medan [value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event" tidak akan terikat pada komponen anak, jadi tiada apa yang akan dipaparkan sehingga ia menyegarkan dan mendapat data daripada pangkalan data.

Apakah kemungkinan yang boleh saya cuba laksanakan?

Saya cuba melaksanakan ngOnChange tetapi tidak berjaya.

P粉463418483P粉463418483211 hari yang lalu411

membalas semua(2)saya akan balas

  • P粉658954914

    P粉6589549142024-03-22 14:12:38

    Senarai Pendidikan yang dimuatkan tidak berubah apabila anda menukar sifat item dalam senarai. Cuba muat semula senarai (this.loadedEducations = returnedEducations) atau gunakan pengurusan negeri dalam projek anda

    balas
    0
  • P粉022723606

    P粉0227236062024-03-22 13:08:51

    Punca masalah adalah sebarang perubahan dalam @Input() 无法检测到对象和数组内部的更改,因为它们都是 引用类型。您的 education 属性是一个对象,因此在父组件中进行的直接改变属性的更改(例如 education.school = 'newValue' )不会触发子组件的属性 @Input() education

    Terdapat beberapa cara untuk menyelesaikan masalah ini, setiap satu dengan kebaikan dan keburukannya:


    Luluskan hanya sifat yang anda perlukan sebagai primitif

    parent.component.ts

    education: Education = 

    parent.component.html

    
    
    
    
    

    child.component.ts

    export class EducationItemComponent implements OnChanges {
      @Input() school: string;
      @Input() degree: string;
    
      ngOnChanges(changes: SimpleChanges): void {
        // will emit whenever .school or .degree is changed in the parent
      }
    }

    Kelebihan:

    • Mudah dan intuitif untuk digunakan, berfungsi "hanya"
    • Hantar perubahan kepada komponen kanak-kanak tanpa boilerplate tambahan

    Kelemahan:

      Boilerplate tambahan diperlukan untuk
    • menerima perubahan kepada komponen kanak-kanak. Apabila bilangan bertambah, ia menjadi sukar digunakan@Input
    • Anda kehilangan gandingan semantik antara komponen ibu bapa dan anak, ia sebenarnya terikat dengan antara muka yang dikongsi (iaitu
    • antara muka) Education
    • Tidak berskala dengan baik jika sifat juga merupakan jenis rujukan, dalam hal ini sifat ini juga perlu dibongkar dan diluluskan sebagai primitif

    Bina semula objek dalam induk apabila ditukar

    parent.component.ts

    education: Education = 
    
    updateEducation(educationProps: Partial): Education {
      this.education = {
        ...this.education, // Note: You may want to 'deep clone' your object depending on how nested it is
        ...educationProps
      }
    }

    Klon Dalam< /a>

    parent.component.html

    
    
    
    
    

    child.component.ts

    export class EducationItemComponent implements OnChanges {
      @Input() education: Education;
    
      ngOnChanges(changes: SimpleChanges): void {
        // will emit whenever updateEducation() is called in the parent
      }
    }

    Kelebihan:

    Kelemahan:

      Memerlukan boilerplate tambahan untuk
    • menghantar perubahan kepada komponen anak, iaitu mencipta fungsi berlebihan updateEducation() dalam komponen induk

    Salurkan elemen reaktif ke dalam komponen anak anda seperti

    dan langgan terus perubahanBehaviorSubject

    parent.component.ts

    educationSubject: BehaviorSubject = new BehaviorSubject(  )
    
    updateEducation(educationProps: Partial): Education {
      const updatedEducation: Education = {
        ...this.education, // Note: You may want to 'deep clone' your object depending on how nested it is
        ...educationProps
      }
      this.educationSubject.next(updatedEducation}
    }

    parent.component.html

    
    
    
    
      
      
    

    child.component.ts

    export class EducationItemComponent implements OnChanges {
      @Input() educationSubject: BehaviorSubject;
    }

    child.component.html

    
      

    {{ education.school }}

    Kelebihan:

    • Kawalan penuh ke atas penghantaran/langganan acara. Ini bagus untuk sebarang kesan sampingan lain yang anda ingin cetuskan
    • Boleh diperluaskan dengan mudah untuk menggunakan banyak komponen, cth. meletakkan educationSubject ke dalam perkhidmatan dan menyuntik perkhidmatan yang sama ke dalam mana-mana komponen yang memerlukannya
    • Juga menyokong penggunaan objek tidak berubah< /里>
    • Tiada boilerplate tambahan diperlukan untuk menerima perubahan kepada subkomponen

    Kelemahan:

    • Memerlukan boilerplate tambahan untuk menghantar perubahan kepada komponen anak, iaitu mencipta fungsi updateEducation() berlebihan
    • dalam komponen induk
    • Had biasa penggunaan kod reaktif, seperti bermutasi hanya melalui strim, perlu mengelak daripada berhenti melanggan (jika tidak menggunakan | async), dsb.

    balas
    0
  • Batalbalas