Constructor of Component invoked on two separate occasions

In my child component, the id property is randomly set like this:

export class FileSelectionComponent implements AfterViewInit {
  public type = 'app-file-selection';
  public id = 'FileSelection#' + Math.random().toString(16).slice(2, 8);
  @Input() jspinst: any;
  public x;
  public y;
  public selected_file: string;

  constructor(public dialog: MatDialog, private httpClient: HttpClient) {
    this.selected_file = '';
    console.log('constructor called');
    console.log(this.id);
  }
  ngAfterViewInit() {
    ...
    this.jspinst.addEndpoint(this.id, { anchor: 'Right'}, Endpoint1);
    this.jspinst.addEndpoint(this.id, { anchor: 'Left'}, Endpoint2);
    this.jspinst.draggable(this.id);
  }
}

The parent component looks like this:

export class FlowComponent implements OnInit, AfterViewInit, OnChanges {
 public nodes: Array<any>;
 public jspl;

  constructor() {
    this.nodes = [];
    this.jspl = jsPlumb.getInstance();
  }

  addNode(type) {
        let nn = new FileSelectionComponent();
        this.nodes = this.nodes.concat([nn]);
        s = this.nodes;
        console.log('object created and added');
  }

  ngAfterViewInit() {
    s = this.nodes;
    this.jspl.bind('connection', function (info) {
      console.log(info.sourceId+' ----> '+info.targetId); 
      console.log(s[0].id+' ----> '+s[1].id); 
      console.log(Object.keys(s[0]));
      console.log(Object.values(s[0]));
    });
  }
}

When I click a button to call the addNode method, the constructor for the FileSelectionComponent is triggered twice, generating two different ids. This makes it difficult to retrieve the correct nodes when the connection event is fired. I have checked several solutions but none seem to work:

  1. The button has type="button".
  2. I am not bootstrapping both parent and child components.
  3. I have closed the selector tag in the host component's template.
  4. There is no
    platformBrowserDynamic().bootstrapModule(AppModule);
    in my code.
  5. No error messages are displayed by the compiler.

The template for the parent component is as follows:

<div id="cont">
  <div *ngFor="let n of nodes">
    <app-file-selection [jspinst]="jspl" *ngIf="n.type === 'app-file-selection'"></app-file-selection>
  </div>
</div>
  <button type="button" mat-icon-button matTooltip="Files selection" (click)="addNode('file-selection')"><mat-icon aria-label="Side nav toggle icon">insert_drive_file</mat-icon></button>

I have tried moving the random assignment inside the constructor (which causes two ids - one recognized by jsplumb and one received by the parent component), and within the OnInit (which results in just one id not known by the parent component).

Answer №1

Utilizing the

<app-file-selection></app-file-selection>
tag automatically instantiates the component by default, eliminating the need for manual instantiation in both the template and logic. Angular components typically do not require the use of New.

An alternative approach could be:

this.nodes = new BehaviorSubject<Array<any>>([]);
this.fileSelectorNodes = [];

ngOnInit() {
  this.nodes.subscribe(nodes => {
    this.updateNodes(nodes);
  });
}

addNode(type) {
  const nodes = this.nodes.getValue();
  nodes.push(type);
  this.nodes.next(nodes);
}

updateNodes(nodes: Array<any>) {
  this.fileSelectorNodes = nodes.filter(node => node === 'app-file-selection');
}
<app-file-selection [jspinst]="jspl" *ngFor="let fileSelector of fileSelectorNodes"></app-file-selection>

Answer №2

To retrieve the index of each element in an array when using *ngFor, you can create a local variable with "let i = index". Then, by utilizing (click) and passing the index back to the parent.component.ts file, you can implement your desired logic.

<div *ngFor="let n of nodes; let i = index">
  <<app-file-selection (click)="addNode(i)></<app-file-selection>
</div>

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

The most recent Angular application created with Angular-CLI is experiencing issues when compiling the package.json file

I encountered an issue while attempting to create a new Angular application using angular-cli. The problem arises during the npm package installation process. When I try to initiate the creation of a new Angular application with angular-cli and proceed to ...

What is the process for incorporating a personalized inputComponent JSX <input /> into a react-phone-number-input PhoneInput component?

Instructions to follow when working with code. react-phone-number-input provides the option for users to replace its default <input /> JSX tag with a custom one, requiring the type React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTML ...

Tips for detecting when multiple image sources have finished loading in an *ngFor loop

I have an array of image URLs that are displayed in a repetitive manner using the *ngFor directive in my HTML code. The technology stack used for this project includes Ionic 4 and Angular 10. <div *ngFor="let url of imagesToLoad; let i = index&quo ...

Adjusting the width of Angular Material dropdown menus

I'm currently utilizing the Angular Material dropdown component and have noticed that the width of the UL list element is dependent on the button width. This becomes an issue when I want the dropdown to have a wider width than the button itself. While ...

Error encountered during Angular update from version 8 to 9 - yarn compatibility issue

I recently upgraded my project from Angular version 8 to 9 following the guidelines on angular.io. However, after the upgrade, I encountered an error while trying to run yarn install. Can anyone help me resolve this issue? Error: error @angular-devkit/ ...

What is the best method for altering a route in React while utilizing Typescript?

I recently started coding along with the ZTM course and am working on a face recognition app. Instead of using JavaScript, I decided to use TypeScript for this project in order to avoid using the any type. However, as a beginner in this language, I'm ...

Is it possible to configure a custom timezone for the Angular Material datepicker feature?

I am currently working on an Angular 7 application and I have encountered a challenge with the date field. In this particular field, I am utilizing the Angular Material Datepicker input. However, I have noticed that the datepicker automatically captures th ...

An effective approach to positioning HTML elements at specific X and Y coordinates

I have an innovative project idea! The concept is to enable users to create points by clicking on the display. They can then connect these points by clicking again. However, I am facing a challenge when it comes to creating HTML elements at the exact loc ...

I encountered an issue where TypeScript does not recognize the type of a variable resulting from object destructuring

I'm attempting to utilize a variable from a destructuring expression as part of another object, but Typescript is not correctly recognizing its type. Here is an example of what I am trying to achieve: // defining a data structure type Data = { fir ...

Generating an Observable that connects with a pre-existing function

Currently, I've been attempting to connect the onCompleteItem array function from the ng2-file-upload package with an RxJS Observable method that can be subscribed to. The function in question looks like this: onCompleteItem(item: FileItem, response ...

Is there a way for me to pass the templateUrl data from the parent component to another component

Currently, I am in the process of learning Angular2 and facing a situation where I have a dropdown that appears on multiple pages. Each time it is called, the contents of the dropdown change, but the structure remains the same. This is why I have set it up ...

Tips for extracting individual keys from an object and transferring them into a separate object

I have an array of objects containing all the form data. However, I need to format this data differently before sending it to the backend. Each object needs to be fetched separately and then pushed into another object as shown below. The current data looks ...

Attempting to retrieve data from cloud Firestore utilizing keyvalue in Angular

My database stores user information under the 'users' collection. I can access this data using the following code: In my service: users$ = this.afs.collection<Users[]>('users').valueChanges(); In my component: public users = t ...

Having trouble assigning an initial value to ngx-bootstrap typeahead

Hello there, I am currently using Angular version 16 with ngx-bootstrap version 11.0.2. I am facing an issue where I cannot set a default value for a control. When a user selects data from a suggestive search and it gets saved in the database, I want that ...

Types of Axios responses vary depending on their status codes

I am looking to create a specific type for axios responses based on the status code: types: type SuccessfulResponseData = { users: .... }; interface SuccessfulResponse extends AxiosResponse<SuccessfulResponseData, any> { status: 200; } ty ...

Utilizing Observable Data in Angular 4 TypeScript Components

Looking to extract and assign a JSON value obtained from an API into a variable. Here is an example: TS this.graphicService.getDatas().subscribe(datas => { this.datas = datas; console.log(datas); }); test = this.datas[0].subdimensions[0].entr ...

Can someone please provide guidance on how I can access the current view of a Kendo Scheduler when switching between views, such as day view or week

<kendo-scheduler [kendoSchedulerBinding]="events" [selectedDate]="selectedDate" [group]="group" [resources]="resources" style="height: 600px;" [workDayStart]="workDayStart" [workDayEnd] ...

What is causing this error to appear during the npm install process in my Angular project?

I encountered an issue in my Angular 7 project recently. When running npm install, the following error occurred: npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: <a href="/cdn-cgi/l/email-pro ...

Combine all JavaScript files into a single file for an Angular 2 application

I've been working on an Angular 2 application. While I can successfully minify the TS/JS files using "uglify", I'm wondering if there's a way to combine all JS files into a single file for faster rendering. https://i.sstatic.net/EVBxU.jpg ...

The parameter 'response' is assumed to be of type 'any' and is not explicitly declared

In my attempt to send data from an angular HTML page to MVC core and receive a response, I encountered an error when trying to use the subscribe method: Parameter 'res' implicitly has an 'any' type. Below is the code snippet: import ...