The error message indicates a change in the binding value within the template, resulting in an

This is the structure of my component A :

<nb-tab tabTitle="Photos" [badgeText]="centerPictures?.pictures?.length" badgePosition="top right" 
            badgeStatus="info">
              <app-center-pictures #centerPictures [center]="center"></app-center-pictures> //Child component B
</nb-tab>
<nb-tab tabTitle="Facilities" [badgeText]="centerFacilities?.facilities?.length" badgePosition="top right" badgeStatus="info">
              <app-club-facilities #centerFacilities [centerId]="center.id"></app-club-facilities> // Child component C
</nb-tab>
<nb-tab tabTitle="Prices" [badgeText]="centerPrices?.priceRules?.length" badgePosition="top right" badgeStatus="info">
              <app-center-prices #centerPrices [currency]="center.currenciesAccepted"></app-center-prices> // Child component D
</nb-tab>

I encountered this error :

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'badgeText: null'. Current value: 'badgeText: 0'

I understand the issue but I'm unsure how to resolve it. It pertains to the DOM [badgeText] and not a function within A. Thank you

EDIT: Component A

IMPORTS

@Component({
  selector: 'app-center-detail',
  templateUrl: './center-detail.component.html',
  providers: [CentersService, PictureService],
  styleUrls: ['center-detail.component.css']
})

export class CenterDetailComponent implements OnInit {

  @ViewChild ('centerPictures') centerPictures;

  get centerPicturesCount(): number {
      console.log(this.centerPictures);
      return this.centerPictures.pictures.length;
  }

  center: Center;
  errorMessage: string;
  success: string;
  edit: boolean = false;

  constructor(
    private centerService: CentersService,
    private route: ActivatedRoute,
    private pictureService: PictureService
  ) { }

  ngOnInit() {
    this.getCenter();
  }

  getCenter() {
    const id = this.route.snapshot.paramMap.get('id');
    this.centerService.getCenter(id)
      .subscribe(
        center => this.center = center,
        error => {
          if (error.status === 404) {
            this.errorMessage = "Center not found";
          }
          else {
            this.errorMessage = "An error has occured";
          }
        }
      );
  }

  processFile(image, type: string) {
    this.success = null;
    this.errorMessage = null;

    if (image.files.length) {
      let picture = new UploadPicture(image.files[0]);
      this.pictureService.addCenterPicture(this.center.id, picture.header(type))
        .subscribe(
          () => {
            this.getCenter();
            this.success = 'Header picture has been successfully changed !';
          },
          error => this.errorMessage = error.message
        )
    }
  }
}

Component B :

IMPORTS

  @Component({
    selector: 'app-center-pictures',
    templateUrl: 'center-pictures.component.html',
    providers: [PictureService],
    styleUrls: ['center-pictures.component.css']
  })
export class CenterPicturesComponent implements OnInit {

  @Input() center: Center;
  facilities: CenterFacilities[];
  pictureUrl = environment.pictureUrl + '/';

  @ViewChild('updateData') updateData: TemplateRef<any>;
  window: NbWindowRef;

  pictures: PictureData[];
  uploads: UploadPicture[] = [`enter code here`];
  uploading: boolean = false;

  error: string;
  success: string;
  disabled: boolean = false;

  constructor(
    private pictureService: PictureService,
    private centersService: CentersService,
    private windowService: NbWindowService
  ) { }

  ngOnInit() {
    this.centersService.getCenterFacilities(this.center.id)
      .translate(
        facilities => {
          this.facilities = facilities
        },
        error => this.error = error.message
      )
    this.getCenterPictures();
  }

  getCenterPictures() {
    this.pictureService.getCenterPictures(this.center.id)
      .subscribe(
        pictures => this.pictures = pictures,
        error => this.error = error.message
      );
  }

  processFile(image) {
    this.error = null;
    this.success = null;
    if (image.files.length) {
      let upload = new UploadPicture(image.files[0]);
      this.uploads.push(upload);
    }
  }

  removeUpload(upload) {
    const index = this.uploads.indexOf(upload);
    this.uploads.splice(index, 1);
  }

  uploadPictures() {
    this.error = null;
    this.success = null;
    if (!this.uploads.length) {
      return this.error = 'Please choose a picture to upload';
    }
    this.uploads.forEach((upload) => {
      this.uploading = true;
      this.pictureService.addCenterPicture(this.center.id, upload.picture())
        .subscribe(
          picture => {
            this.success = '\'' + picture.name + '\' has been uploaded';
            this.getCenterPictures();
            this.uploading = false;
          },
          error => this.error = error.message
        );
    });
    this.uploads.length = 0;
  }

  openWindow(picture: PictureData) {
    this.window = this.windowService.open(this.updateData, {
      title: picture.name,
      context: { picture: picture },
    });
  }

  updatePicture(picture: PictureData) {
    this.error = null;
    this.success = null;
    this.pictureService.updateCenterPicture(this.center.id, picture.id, {
      caption: picture.caption,
      activity: picture.activity,
      facilityId: picture.facilityId,
      isIndoor: picture.isIndoor
    }).subscribe(
      () => {
        this.success = '\'' + picture.name + '\' has been successfully updated';
        if (this.window)
          this.window.close();
      },
      error => this.error = error.message
    );
  }

  removePicture(id: string, name: string) {
    this.success = null;
    this.error = null;
    if (!this.disabled) {
      this.disabled = true;
      this.pictureService.deleteCenterPicture(this.center.id, id)
        .subscribe(
          () => {
            this.getCenterPictures();
            this.success = '\'' + name + '\' has been successfully removed';
            this.disabled = false;
          },
          error => this.error = error.message
        );
    }
  }
}

Answer №1

Give this a shot. Insert the following code snippet into child component B

@Output() updatedPictureCount: EventEmitter<number>;
constructor() {
    this.updatedPictureCount = new EventEmitter<number>();
}
fetchCenterPictures() {
    this.pictureService.getCenterPictures(this.center.id)
      .subscribe(
        pictures => {
          this.updatedPictureCount.emit(pictures.length);
        },
        error => this.error = error.message
      );
}

Now, onto component A:

public totalPicturesDisplayed: number = 0;
updatePictureCount(value: number) {
    this.totalPicturesDisplayed = value;
}

Lastly, in your Template:

<nb-tab tabTitle="Photos" [badgeText]="totalPicturesDisplayed" badgePosition="top right" 
            badgeStatus="info">
    <app-center-pictures (updatedPictureCount)=updatePictureCount($event) #centerPictures [center]="center"></app-center-pictures> //Child component B
</nb-tab>

Answer №2

Begin by inserting the following code snippet in your componentA.ts file

@ViewChild ('centerPictures') centerPictures;

get totalCenterPictures(): number {
    return this.centerPictures.pictures.length;
}

Next, update your template as shown below:

<nb-tab tabTitle="Photos" [badgeText]="totalCenterPictures" badgePosition="top right" 
            badgeStatus="info">
              <app-center-pictures #centerPictures [center]="center"></app-center-pictures> //Child component B
</nb-tab>

Answer №3

Issue Resolved (credit to Akai Crystal)

Component A :

public totalPictures: number = 0;
updateTotalPictures(value: number) {
   this.totalPictures = value;
}

Component B :

@Output() totalPictures = new EventEmitter<number>();
fetchPictures() {
   .
   .
   .
   receivedPictures => {
      this.receivedPictures = receivedPictures,
      this.totalPictures.emit(receivedPictures.length);
   }

Template :

<nb-tab tabTitle="Photos" [badgeText]="totalPictures" badgePosition="top right" 
badgeStatus="info">
   <app-display-pictures (totalPictures)=updateTotalPictures($event) #displayPictures 
   [center]="center"></app-display-pictures>
</nb-tab>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for accessing and modifying local files in Angular 2

Is there a method in Angular 2 to access files from an absolute path? I have utilized the 'filesaver' library for file saving, storing the files locally in txt/json formats. For instance: let blob = new Blob([document.getElementById(&apos ...

Retrieve specific data points within a dataset

Within the dataset provided, I am attempting to retrieve specific values. { "id": "0f0126f5-aed3-49bb-97dd-7ad2d00b67a4", "retirementData": "{\"benefits\":[{\"availableBenefitOptions\":{\"anniversaryDate\":\"202 ...

Modifying an element's value according to user input: Step-by-step guide

Within my dropdown menu, there is a single option labeled "Others". Upon selecting this option, a textbox appears allowing me to input custom text. Is it possible to dynamically update the value of the <option value="Others">Others</option>, ...

Guide on integrating an Angular 10 Component into a cell in Ag-Grid

I am currently working with an Angular10 component, specifically a toggle switch, that I need to integrate into a specific column within my ag-grid cell. Currently, I am using a basic HTML checkbox in the following manner: colDefs: ColDef[] = [ { fiel ...

What is the best method to extract the values of objects in an array that share

var data= [{tharea: "Rare Disease", value: 3405220}, {tharea: "Rare Disease", value: 1108620}, {tharea: "Rare Disease", value: 9964980}, {tharea: "Rare Disease", value: 3881360}, ...

Interactive form control for location details including country, state, district, and town

I am struggling with adding dynamic form controls on dropdown change. I have been able to add them, but encountered an error preventing me from retrieving the value in 'formName.value'. The specific error message states: "Error: There is no Form ...

Include required "user" after middleware in Express with Typescript and Passport setup

I find myself constantly having to include code like if (!req.user) return res.status(401).send() The first solution that comes to mind is creating an express middleware for this. However, even though I can prevent non-logged in users from accessing the r ...

Issue with Ionic Map and location services

After extensively searching for solutions to my current error, I have found that all existing solutions are outdated and do not work for me. The issue began when I tried to incorporate the user's current location into my app, which utilizes Google Map ...

What's the best way to ensure you're linting the correct file type for importing in Web

Upon installation of WebStorm, I encountered an issue when opening an existing Vue/TypeScript project. The IDE was not correctly importing and linting some file imports that were functioning properly through ESLint/webpack. In my usage of Vue 2.x with com ...

Guide to reference points, current one is constantly nonexistent

As I work on hosting multiple dynamic pages, each with its own function to call at a specific time, I encounter an issue where the current ref is always null. This poses a challenge when trying to access the reference for each page. export default class Qu ...

Angular 5 offers the capability to use mat-slide-toggle to easily display and manipulate

I am experiencing an issue with displaying data in HTML using a mat-slide-toggle. The mat-slide-toggle works correctly, but the display does not reflect whether the value is 1 (checked) or 0 (unchecked). Can anyone provide some ideas on how to resolve this ...

Ways to incorporate the use of the useAsync hook within a submit function

After importing useAsync(hook from 'react-async') and attempting to utilize it post form submission for a POST request, a "can't use hooks inside functions" error is encountered due to the rules of hooks. How can this issue be resolved in o ...

Struggling to update TypeScript and encountering the error message "Unable to establish the authenticity of host 'github.com (192.30.253.113)'"

While attempting to update my version of TypeScript using npm, I ran into an issue when trying to execute the following command: localhost:Pastebin davea$ npm install typescript/2.8.4 --save-dev The authenticity of host 'github.com (192.30.253.113)&a ...

Bespoke Socket.io NodeJS chamber

I am currently developing an application involving sockets where the requirement is to broadcast information only to individuals within a specific room. Below is a snippet of the code from my server.ts file: // Dependencies import express from 'expre ...

Provider with factory for the root Angular 6 library

I'm currently in the process of developing a library that requires a configuration input from the host application. During the building phase of the library, I encounter the following warning: Warning: Can't resolve all parameters for CacheServ ...

Ways to display a popup when hovering over a marker in ngx-mapbox-gl

I have a current implementation that displays markers and popups on click of markers. We now need to update it to show popups on hover instead. Here is the structure of my template: <mgl-map #map1 [style]="'mapbox://styles/mapbox/streets ...

Encountering difficulty obtaining return value from asynchronous function, await behaving inconsistently in Vue API Service

I am in the process of developing a new service to interact with my API. I am not very familiar with async/await, but I have encountered a puzzling issue that doesn't seem to align with what I've read in the documentation. When attempting to use ...

Encountered CORS error when attempting to access the dynamic menu API after logging

Currently, I am working on an Angular 6 and Codeigniter project. In this project, the slider and navigation menu bar are being fetched dynamically through a REST API. Everything runs smoothly until the login process, where a CORS error is encountered. htt ...

Setting the root directory and output directory can be a bit tricky when dealing with source code scattered across multiple folders. Here's

Utilizing TypeScript in my Node.js project, I previously had a directory structure that looked like this: node_modules src -Models -Routes -Middlewares -Controllers -index.ts package.json tsconfig.json In ...

Expanding a given type using Typescript

My goal is to construct a custom table using Angular, where I aim to define a TableItem type that enforces the presence of a label property for every item added to the table. For instance, consider this example: <app-my-table [items]="items&qu ...