如何使用后面的代码加载Nativescript Angular子组件? [英] How do I load a Nativescript Angular child component using code behind?
问题描述
我正在尝试将自定义子级Angular组件添加到在父级模板中定义的GridLayout中.父级需要支持一些它知道如何构建和交互的组件,但是它必须能够在GridLayout中指示的时间和位置放置它们.
I am trying to add a custom child Angular component to a GridLayout which is defined in the parent's template. The parent needs to support a few components which it knows how to build and interact with, but it must be able to place them when and where instructed within the GridLayout.
- 我可以在模板中指定我的SampleComponent子级,然后显示它.
- 如果我尝试使用后面的代码将SampleComponent添加到GridLayout中,则grid.addChildChild逻辑不会给出任何错误,但是该组件无法显示.
- 如果我使用后面的代码将一个Button添加到网格中,它将按预期显示.
我了解我正在尝试加载Component vs. Button,但是我的组件确实扩展了ContentView.我已经看到了一些关于Builders的讨论,但是它们似乎是从源代码进行编译的,其中我的子组件是由我的父代构建的,并且它们使用.xml模板.我确实尝试查看ComponentBuilder,但找不到任何可帮助我理解如何使用它的文档.
I understand that I am trying to load a Component vs. a Button, but my component does extend ContentView. I have seen some discussions around Builders, but they seemed to be compiling from source code, where my child components are built with my parent, and they use .xml templating. I did try looking at ComponentBuilder, but I cannot find any documentation that helps me understand how I might use it.
下面是我的示例中最相关的3个功能,这些功能是通过用户键入示例"或按钮"并单击添加"以触发onTap()来启动的.
The most relevant 3 functions of my sample are below, initiated by the user keying in 'sample' or 'button' and clicking ADD to fire onTap().:
onTap() {
this.textField.nativeElement.dismissSoftInput();
let name = this.textField.nativeElement.text.toLowerCase();
var component: any;
console.log(`Adding component ${name}`);
switch( name ) {
case 'sample':
component = this.buildSample();
break;
case 'button':
component = this.buildButton();
break;
default:
console.error("User keyed in invalid response");
return;
}
console.log("Adding component to grid");
let grid: GridLayout = this.gridField.nativeElement;
grid.addRow( new ItemSpec( 1, GridUnitType.AUTO ));
let label = new Label();
label.text = name;
grid.addChild( label );
GridLayout.setRow( label, this.row );
grid.addChild( component );
GridLayout.setRow( component, this.row );
GridLayout.setColumn( component, 1 );
this.row++
}
private buildButton(): Button {
let button = new Button();
button.text = `Button for row${this.row}`;
return button;
}
private buildSample(): SampleComponent {
let sample = new SampleComponent();
sample.setting = 259;
return sample;
}
推荐答案
使用NativeScript Angular范例进行这项工作的关键似乎是指令和注入.
The keys to make this work using a NativeScript Angular paradigm seem to be directives and injection.
我的解决方案是使用指令加载我的子指令.该指令使用注入来获取在父级视图中构建子级组件所需的引用.
My solution is to use a directive to load my child directive. The directive uses injection to get the references necessary to build the child component within the parent's view.
所以,在下面的示例中,
So, in my sample below,
<StackLayout *LoadChildComponent></StackLayout>
触发我的LoadChildDirective,但也包装了堆栈元素
fires my LoadChildDirective, but also wraps the stack element
<ng-template loadChild><StackLayout></StackLayout></ng-template>
这意味着指令的视图上下文位于堆栈元素外部的位置.
This means that the view context of the directive is the position just outside of the stack element.
- 该指令可以像注入组件一样使用注入来获取有趣的东西,使我们可以加载诸如ViewContainerRef之类的子组件.
import { ViewChild, ElementRef, Component,OnInit, ComponentFactoryResolver } from '@angular/core';
import { LoadChildDirective } from './load.child.directive';
@Component({
moduleId: module.id,
selector: 'parent',
template: `
<StackLayout>
<StackLayout *loadChild></StackLayout>
<Button id="dfSaveButton" text="save"></Button>
</StackLayout>
`})
export class ParentComponent implements OnInit {
constructor() {}
ngOnInit() {
console.log("In parent ngOnInit");
}
}
儿童负荷指令
import { Directive, OnInit , ViewContainerRef, ComponentFactoryResolver } from "@angular/core";
import { ChildComponent } from './child.component';
@Directive({
selector: "[loadChild]" // directive tag used in parent
})
export class LoadChildDirective implements OnInit {
constructor(private vcRef: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver
) {
console.log("In loadChildDirective constructor with vcRef=" + vcRef);
}
ngOnInit() {
console.log("In LoadChildDirective ngOnInit with vcRef=" + this.vcRef);
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(ChildComponent);
const viewContainerRef = this.vcRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent<ChildComponent>(componentFactory);
const child = <ChildComponent>componentRef.instance;
}
}
参考
https://angular.io/guide/dynamic-component-loader#dynamic-component-loading
这篇关于如何使用后面的代码加载Nativescript Angular子组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!