我有一个按钮组件fancy-textbox
。我想让用户可以动态添加新的fancy-textbox
,但是它们在文本框上方有不同的标签,这些标签基于fancy-textbox
本身(或者来自父级)的唯一范围变量所有fancy-textboxes
之间未共享的范围变量。我该怎么做呢?目前,我直接在我的模板显示和隐藏中使用它,但我希望能够动态添加更多这个"的实例。编程:
<div *ngIf="showTextBox">
<fancy-textbox labelForBox="TextBox 1"></fancy-textbox>
</div>
如果仅在一个特定区域的DOM中创建花式文本框,那就很好。但是,我想要做的是能够在DOM的不同部分动态创建组件。
<div class="container">
<div class="navsection"><input id="classname" type="text"><button (click)="createFancyButton()">Create Fancy Button</button></div>
<div class="topsection">
</div>
<div class="midsection">
</div>
<div class="botsection">
</div>
<div class="footsection"></div></div>
鉴于上面的模板...假设用户在文本框中输入了类名(例如botsection)并点击了&#34; createfancybutton按钮),我想要&#34;&#34;
&#34; <fancy-button></fancy-button>
&#34;要放入页面的相应部分,我希望能够动态地创建&#34;独立&#34;花式按钮的实例&#34;在页面模板的不同部分。我可以坚持使用ng-for 3 ng-if语句,但这似乎不切实际。寻找更好的替代方案......
更新:所以步骤将是:
1)用户进入&#34; midsection&#34;进入文本框。
2)用户点击按钮&#34;创建花式按钮&#34;
3) - <fancybutton></fancybutton>
组件将添加到div下,类名为#34; midsection&#34; -
用户可以重复点击相同的&#34;创建花式按钮&#34;按钮在此下创建更多。如果用户将输入框更改为&#34; topsection&#34;,那么当用户点击&#34;创建花式按钮&#34;时,fancybutton组件将添加到div下,其中&#34; topsection&#34;。
如果用户输入&#34; newsection&#34;,那么新的div为classname&#34; newsection&#34;将在div下使用classname&#34; container&#34;创建,而fancybutton组件将添加到div中,类名为&#34; newsection&#34;。
答案 0 :(得分:1)
在组件中添加一系列标签。
使用* ngFor迭代此数组并为每个标签生成一个精美的文本框。
要添加新的花式文本框,请向数组添加新标签。
<fancy-textbox *ngFor="let label of labels" [labelForBox]="label"></fancy-textbox>
在组件中:
labels: string[] = [];
// to add a fancy textbox:
this.labels.push('new label');
答案 1 :(得分:1)
您需要动态加载组件
这是我的解决方案
<强> Parent.component.ts 强>
import { Component, OnInit, ViewChild, ViewContainerRef, Input, ComponentFactoryResolver, ReflectiveInjector } from
"@angular/core";
import { FancyButtonCompoent } from "../FancyButton.component";
@Component({
moduleId: module.id,
selector: "app-parent",
templateUrl: "parent.component.html",
styleUrls: ["parent.component.css"],
entryComponents: [FancyButtonCompoent]
})
export class ParentCompoent {
@ViewChild("midsection", { read: ViewContainerRef })
midsectionContainer: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver) {
}
createFancyButton() {
//Name Is Fancybutton data binding property
var yourdatavalues= {Name:'myname'}
this.createDynamicbutton({
input: yourdatavalues,
});
}
//you can add your own model to get what you want like remove,move
// var dynamiccompoent={Data:yourmodel,compoentcontainer:any}
//fancybuttonarray:dynamiccompoent[];
fancybuttonarray:any[];
createDynamicbutton(elementData) {
if (!elementData) {
return;
}
// Inputs need to be in the following format to be resolved properly
let inputProviders = Object.keys(elementData.inputs)
.map((inputName) => { return { provide: inputName, useValue: elementData.inputs[inputName] }; });
let resolvedInputs = ReflectiveInjector.resolve(inputProviders);
// We create an injector out of the data we want to pass down and this components injector
let injector = ReflectiveInjector
.fromResolvedProviders(resolvedInputs, this.midsectionContainer.parentInjector);
// We create a factory out of the component we want to create
let factory = this.resolver.resolveComponentFactory(DefaultButtonComponent);
// We create the component using the factory and the injector
let component = factory.create(injector);
this.midsectionContainer.insert(component.hostView)
//your getting every instance of fancy button instance into array
this.fancybuttonarray.push.(component )
//if you want to clear elment if you wish
//this.fancybuttonarray[0].destroy()
//this.fancybuttonarray[1].destroy()
}
}
<强> parent.component.html 强>
<div class="row col-lg-12" >
<div #midsection >
</div>
</div>
<强> Fancybutton.compoent.ts 强>
import { Component, OnInit, Injector } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'Fancy-button',
templateUrl: 'Fancybutton.component.html'
})
export class FancybuttonComponent {
inputelement:yourDatamodel
constructor(private injector: Injector) {
this.inputElement = this.injector.get('inputElement');
}
}
<强> Fancybutton.compoent.html 强>
<div>
<button title="inputelement.Name"(click)r ="alert(inputelement.Name)"></button>
</div>
<强>更新强>
这是关于使用angular2
加载动态子组件的好文章还可以使用 Plunker example
答案 2 :(得分:1)
从“架构上”看这个,并利用JS / TS OO类继承,我会个人 考虑添加'复合组件'('cc':跟随OO'复合'模式)到每个部分(例如:<top-section-cc-fancytextboxes...></>
或<bot-section-cc-fancytextboxes...></>
)。这些用作各种<fancy-textbox>
类型的“占位符”,每个cc(复合组件)内可以是零个或多个实例。
现在,每个复合组件从基类/接口组件(例如:<base-section-cc-fancytextboxes>
)派生/实现,其中包含管理添加多个<fancy-textbox>
类型的基本方法。但是,派生类方法会“知道”在哪里添加正确的<fancy-textbox>
s(可能是*ngFor
'd数组,如上所述)。至于实例化特定类型的<fancy-textbox>
,也许利用类工厂模式也很有用 - 可能是一个AJ2服务提供者,它返回实例并由复合组件驱动。
无论如何,使用AJ2内置的TS OO,尽管有详细信息,但这是个人将用于解决此特定问题的向量。这只是一个想法。
答案 3 :(得分:1)
我认为您不需要任何其他范围/组件。这样的事情应该有效。
组件(TypeScript):
sections: {[key] : string[]} = {};
createFancyButton: (section: string) => {
if (!this.sections[section]) {
this.sections[section] = [];
}
this.sections[section].push('');
}
getSectionKeys: () => {
return Object.keys(this.sections);
}
“sections”属性是一个可索引对象,这意味着它的行为类似于哈希表。 sections对象的每个属性(“key”)都是一个字符串数组,表示花哨的按钮值(ngModel)。
模板(HTML)
<div class="container">
<div class="navsection">
<input #section type="text" placeholder="section" />
<button (click)="createFancyButton(#section.value)">Create Fancy Button</button>
</div>
<div *ngFor="let key of getSectionKeys()" [class]="key">
<fancy-textbox *ngFor="let textBox of sections[key]" [(ngModel)]="textBox"></fancy-textbox>
</div>
</div>
有一个模板引用变量(#section),可以方便地访问模板中的DOM元素。然后我们* ngFor来自部分哈希表的键来创建每个部分div。最后,我们* ng对每个部分的字符串数组。
有关模板参考变量的更多信息,请点击此处。 https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars
注意:可能存在拼写错误,因为我没有对此进行测试。
答案 4 :(得分:0)
这是以编程方式构建和添加组件的方式:
type
TWebBrowser = class(SHDocVw.TWebBrowser)
protected
procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
end;
procedure TWebBrowser.WMGetDlgCode(var Msg: TWMGetDlgCode);
begin
inherited;
Msg.Result := Msg.Result or DLGC_WANTARROWS;
end;