组件的构造函数调用了两次
Component's Constructor called twice
所以我有这个 child 组件,其中 id
属性 是随机设置的:
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);
}
}
和 parent 组件是这样的:
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); //this output
console.log(s[0].id+' ----> '+s[1].id); // and this output are not the same while they should
console.log(Object.keys(s[0]));
console.log(Object.values(s[0]));
});
}
}
当我点击一个按钮时,addNode
方法被调用,你可以猜到 FileSelectionComponent
的构造函数被调用了两次,生成了两个不同的 ID,这让我无法检索connection
事件触发时的相关节点。
我发现了一些类似的问题,例如 ,但 none 帮助:
- 我的按钮上有一个
type="button"
- 我没有引导 parent 和 child 组件,实际上我没有引导它们中的任何一个,我已经检查了
app.module.ts
(我什至不知道自举是关于)。
- 我没有忘记关闭主机组件中的选择器标签。
- 我的代码中没有
platformBrowserDynamic().bootstrapModule(AppModule);
。
- 编译器不显示任何错误消息。
parent 的模板是这样的:
<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>
我知道这类问题被问了很多遍,但我的搜索似乎没有帮助,在此先感谢。
编辑
我已经尝试将该随机分配放在构造函数中(导致两个 id,一个被 jsplumb 捕获,一个被 parent 组件接收),并将它放在 OnInit 中(结果只有一个 id 但 parent组件)。
您可以使用局部变量 "let i = index" 来获取 *ngFor 数组的索引(在您的例子中是节点)。并使用(单击)返回,将逻辑写入 parent.component.ts 文件。
<div *ngFor="let n of nodes; let i = index">
<<app-file-selection (click)="addNode(i)></<app-file-selection>
</div>
默认情况下,您的 <app-file-selection></app-file-selection>
标记已经在实例化该组件。这意味着它在您的模板和您的逻辑中都被实例化了。一般来说,您不需要使用带有 angular 个组件的 New。
你可以这样做:
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>
所以我有这个 child 组件,其中 id
属性 是随机设置的:
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);
}
}
和 parent 组件是这样的:
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); //this output
console.log(s[0].id+' ----> '+s[1].id); // and this output are not the same while they should
console.log(Object.keys(s[0]));
console.log(Object.values(s[0]));
});
}
}
当我点击一个按钮时,addNode
方法被调用,你可以猜到 FileSelectionComponent
的构造函数被调用了两次,生成了两个不同的 ID,这让我无法检索connection
事件触发时的相关节点。
我发现了一些类似的问题,例如
- 我的按钮上有一个
type="button"
- 我没有引导 parent 和 child 组件,实际上我没有引导它们中的任何一个,我已经检查了
app.module.ts
(我什至不知道自举是关于)。 - 我没有忘记关闭主机组件中的选择器标签。
- 我的代码中没有
platformBrowserDynamic().bootstrapModule(AppModule);
。 - 编译器不显示任何错误消息。
parent 的模板是这样的:
<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>
我知道这类问题被问了很多遍,但我的搜索似乎没有帮助,在此先感谢。
编辑 我已经尝试将该随机分配放在构造函数中(导致两个 id,一个被 jsplumb 捕获,一个被 parent 组件接收),并将它放在 OnInit 中(结果只有一个 id 但 parent组件)。
您可以使用局部变量 "let i = index" 来获取 *ngFor 数组的索引(在您的例子中是节点)。并使用(单击)返回,将逻辑写入 parent.component.ts 文件。
<div *ngFor="let n of nodes; let i = index">
<<app-file-selection (click)="addNode(i)></<app-file-selection>
</div>
默认情况下,您的 <app-file-selection></app-file-selection>
标记已经在实例化该组件。这意味着它在您的模板和您的逻辑中都被实例化了。一般来说,您不需要使用带有 angular 个组件的 New。
你可以这样做:
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>