简体   繁体   English

多个模板参考变量-Angular 2和TypeScript

[英]Multiple Template Reference Variables - Angular 2 and TypeScript

I am trying to call a function in one component that emits some data to a function in another component, completes some operation and emits the data back to the original component. 我试图在一个组件中调用一个函数,该函数将一些数据发送到另一个组件中的函数,完成一些操作,然后将数据发送回原始组件。 These components are siblings. 这些组件是同级的。 My issue is that Angular doesn't seem to like multiple reference variables in one html file saying that one of my reference variables is undefined. 我的问题是,Angular在一个html文件中似乎不喜欢多个参考变量,说我的参考变量之一未定义。 Any ideas? 有任何想法吗?

HTML 的HTML

<docked-component-picker #compPicker (onComponentRelease)="grid.getMousePosition($event)" [(model)]="model" *ngIf="model.pageState == 1"></docked-component-picker>
<grid #grid (onGetReleaseBack)="compPicker.setNewComponentPosition($event)" [(model)]="model.layout" [editable]="model.pageState" [currentResponsiveRestriction]="model.currentResponsiveRestriction"></grid>

docked-component-picker.ts 停靠组件选择器

@Component({
    selector: 'docked-component-picker',
    templateUrl: './docked-component-picker.component.html',
    providers: [ComponentService]
})

export class DockedComponentPickerComponent {
@Input()
private model: Page;

@Output()
private onComponentRelease: EventEmitter<any> = new EventEmitter();

private components;

private currComponent;

private dragging: boolean;

private parentWidth;

constructor(private _componentService: ComponentService, private _componentFactoryResolver: ComponentFactoryResolver, private _elementRef: ElementRef) {
    let promise = this._componentService.getComponents().then(response => {
        this.components = JSON.parse(response._body);
    });
}

@HostListener('window:mouseup', ['$event'])
onMouseup(event) {
    console.log(event);
    if (this.dragging) {
        this.dragging = false;

        this.onComponentRelease.emit(event);
    }
}

public setNewComponentPosition(event) {
    let pc = new PageComponent({
        component: this.currComponent.template,
        componentId: this.currComponent.id,
        pageId: this.model.id,
        responsiveRestrictions: [
            new ResponsiveRestriction({ sizeType: 0, positionX: event.x, positionY: event.y }),
            new ResponsiveRestriction({ sizeType: 1, positionX: event.x, positionY: event.y }),
            new ResponsiveRestriction({ sizeType: 2, positionX: event.x, positionY: event.y }),
        ],
    });
    this.model.layout.addPageComponent(pc, this.model.currentResponsiveRestriction);
}

/**
* Converts the given container's raw pixel position to grid co-ordinates
 * @param source - the container to convert
*/
private convertToGridPosition(x, y): Position {
    return new Position(Math.round(x / (this.parentWidth / this.model.layout.width)), Math.round(x / this.model.layout.rowHeight));
}

public createComponent(component): void {
    this.currComponent = component;

    this.dragging = true;
}

Needed parts of grid.component.ts grid.component.ts的所需部分

@Output()
    private onGetReleaseBack: EventEmitter<Position> = new EventEmitter();

public getMousePosition(event) {
    let pos = new Position(Math.round(event.offsetX / (this.parentWidth / this.model.width)), Math.round(event.offsetY / this.model.rowHeight));
    this.onGetReleaseBack.emit(pos);
}

Error 错误

ERROR TypeError: Cannot read property 'setNewComponentPosition' of undefined at Object.eval [as handleEvent] (PageComponent.html:4) at handleEvent 错误TypeError:无法在handleEvent处读取Object.eval上未定义的属性'setNewComponentPosition'[作为handleEvent](PageComponent.html:4)

docked-component-picker and grid both live inside the same component. 对接的组件选择器网格都位于同一组件内。 You are trying to catch an event from the grid emitter function "onGetReleaseBack" to execute some logic inside DockedComponentPickerComponent. 您正在尝试从网格发射器函数“ onGetReleaseBack”捕获事件以在DockedComponentPickerComponent内部执行一些逻辑。

If my understanding is correct, here is what I suggest : in your component DockedComponentPickerComponent replace the function setNewComponentPosition by an @Input : 如果我的理解是正确的,这里是我的建议:在你的组件DockedComponentPickerComponent取代由@input功能setNewComponentPosition:

@Input() set componentPosition(event){
    if(event){
        //setNewComponentPosition  logic here
    }        
}

Then you will need to do some other adjustments for this to work. 然后,您将需要进行其他一些调整才能使其正常工作。 in the parent template, replace your 在父模板中,替换您的

<grid #grid 
      (onGetReleaseBack)="setNewComponentPosition($event)" 
      [(model)]="model.layout" 
      [editable]="model.pageState" 
      [currentResponsiveRestriction]="model.currentResponsiveRestriction">
</grid>

In the parent component, you need to create a new function called setNewComponentPosition which will update a class property "componentPosition" that you also need to declare 在父组件中,您需要创建一个名为setNewComponentPosition的新函数,该函数将更新您还需要声明的类属性“ componentPosition”

setNewComponentPosition(newPosition){
    this.componentPosition = newPosition;
}

Finally in the parent template, you need to update the docked-component-picker... to include the newly created property like so : 最后,在父模板中,您需要更新docked-component-picker ...以包括新创建的属性,如下所示:

<docked-component-picker #compPicker 
     [componentPosition]="componentPosition"
     (onComponentRelease)="grid.getMousePosition($event)" 
     [(model)]="model" 
     *ngIf="model.pageState == 1"></docked-component-picker>

The problem is because of using ngIf and #compPicker together. 问题是因为一起使用ngIf#compPicker When the view initializes the compPicker is not yet present it seems, so the variable will be undefined. 当视图初始化compPicker时,它似乎还不存在,因此该变量将是未定义的。

One solution is to add ViewChild inside your parent component to access the child component which is using ngIf : 一种解决方案是在您的父组件内部添加ViewChild来访问使用ngIf的子组件:

@ViewChild('compPicker') compPicker: ElementRef;

Another solution could be to use [hidden]="model.pageState != 1" instead of ngIf . 另一种解决方案是使用[hidden]="model.pageState != 1"代替ngIf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM