사용자 클릭 선택 구성 요소가 있는 동적 탭
구성 요소가 직접(제목으로) 등록할 수 있는 탭 시스템을 설정하려고 합니다.첫 번째 탭은 받은 편지함과 같고, 사용자가 선택할 수 있는 작업/링크 항목이 많이 있습니다. 이러한 각 클릭은 클릭 한 번으로 새 구성 요소를 인스턴스화할 수 있어야 합니다.작업/링크는 JSON에서 제공됩니다.
그러면 인스턴스화된 구성 요소가 새 탭으로 등록됩니다.
이것이 '최고'의 접근법인지 잘 모르겠습니다.지금까지 제가 본 유일한 가이드는 정적 탭에 대한 것인데, 이것은 도움이 되지 않습니다.
지금까지 저는 앱 전체에서 지속되도록 부트스트랩된 탭 서비스만 가지고 있습니다.다음과 같습니다.
export interface ITab { title: string; }
@Injectable()
export class TabsService {
private tabs = new Set<ITab>();
addTab(title: string): ITab {
let tab: ITab = { title };
this.tabs.add(tab);
return tab;
}
removeTab(tab: ITab) {
this.tabs.delete(tab);
}
}
질문:
- 받은 편지함에서 새(다른) 탭을 만드는 동적 목록을 만들려면 어떻게 해야 합니까?나는 약간 추측하고 있습니다.
DynamicComponentBuilder
사용하시겠습니까? - 받은 편지함(클릭 시)에서 구성요소를 생성하여 탭으로 등록하고 표시하는 방법은 무엇입니까?제 생각엔
ng-content
하지만 어떻게 사용하는지에 대한 많은 정보를 찾을 수 없습니다.
편집: 명확히 하려는 시도입니다.
받은 편지함을 메일 받은 편지함으로 생각합니다.항목은 JSON으로 가져오고 여러 항목을 표시합니다.항목 중 하나를 클릭하면 해당 항목 작업 'type'으로 새 탭이 만들어집니다.그러면 유형이 구성 요소가 됩니다.
편집 2: 이미지.
갱신하다
갱신하다
ngComponentOutlet
4.0.0-1987.3에 추가되었습니다.
갱신하다
있습니다.NgComponentOutlet
비슷한 일을 하는 진행 중인 작업 https://github.com/angular/angular/pull/11235
RC.7
// Helper component to add dynamic components
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;
@Input() type: Type<Component>;
cmpRef: ComponentRef<Component>;
private isViewInitialized:boolean = false;
constructor(private componentFactoryResolver: ComponentFactoryResolver, private compiler: Compiler) {}
updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
// when the `type` input changes we destroy a previously
// created component before creating the new one
this.cmpRef.destroy();
}
let factory = this.componentFactoryResolver.resolveComponentFactory(this.type);
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
사용 예
// Use dcl-wrapper component
@Component({
selector: 'my-tabs',
template: `
<h2>Tabs</h2>
<div *ngFor="let tab of tabs">
<dcl-wrapper [type]="tab"></dcl-wrapper>
</div>
`
})
export class Tabs {
@Input() tabs;
}
@Component({
selector: 'my-app',
template: `
<h2>Hello {{name}}</h2>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App {
// The list of components to create tabs from
types = [C3, C1, C2, C3, C3, C1, C1];
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, DclWrapper, Tabs, C1, C2, C3],
entryComponents: [C1, C2, C3],
bootstrap: [ App ]
})
export class AppModule {}
각도도 참조.io 동적 구성 요소 로더
구판 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
이것은 Angular2 RC.5에서 다시 변경되었습니다.
아래 예시를 업데이트하겠지만 방학 전 마지막 날입니다.
이 플런커 예제는 RC.5에서 구성 요소를 동적으로 생성하는 방법을 보여줍니다.
업데이트 - ViewContainerRef.createComponent() 사용
왜냐면DynamicComponentLoader
더 이상 사용되지 않습니다. 접근 방식을 다시 업데이트해야 합니다.
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private resolver: ComponentResolver) {}
updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
});
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
업데이트 - loadNextToLocation 사용
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private dcl:DynamicComponentLoader) {}
updateComponent() {
// should be executed every time `type` changes but not before `ngAfterViewInit()` was called
// to have `target` initialized
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.dcl.loadNextToLocation(this.type, this.target).then((cmpRef) => {
this.cmpRef = cmpRef;
});
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
원래의
당신의 질문에서 당신의 요구사항이 무엇인지 완전히 확신할 수는 없지만, 저는 이것이 당신이 원하는 것을 해야 한다고 생각합니다.
그Tabs
의 각 에 대해 를 생성합니다. component는 "component"와 "component"를 생성합니다.
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
constructor(private elRef:ElementRef, private dcl:DynamicComponentLoader) {}
@Input() type;
ngOnChanges() {
if(this.cmpRef) {
this.cmpRef.dispose();
}
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
this.cmpRef = cmpRef;
});
}
}
@Component({
selector: 'c1',
template: `<h2>c1</h2>`
})
export class C1 {
}
@Component({
selector: 'c2',
template: `<h2>c2</h2>`
})
export class C2 {
}
@Component({
selector: 'c3',
template: `<h2>c3</h2>`
})
export class C3 {
}
@Component({
selector: 'my-tabs',
directives: [DclWrapper],
template: `
<h2>Tabs</h2>
<div *ngFor="let tab of tabs">
<dcl-wrapper [type]="tab"></dcl-wrapper>
</div>
`
})
export class Tabs {
@Input() tabs;
}
@Component({
selector: 'my-app',
directives: [Tabs]
template: `
<h2>Hello {{name}}</h2>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App {
types = [C3, C1, C2, C3, C3, C1, C1];
}
요소에 할 수 방법도 ( 적으로생구요동전방있다습니법달도는)someData
처럼 통과되어야 할 것입니다.type
)
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
cmpRef.instance.someProperty = someData;
this.cmpRef = cmpRef;
});
또한 공유 서비스와 함께 종속성 주입을 사용할 수 있는 일부 지원도 있습니다.
자세한 내용은 https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html 를 참조하십시오.
저는 댓글을 달 만큼 쿨하지 않아요.저는 rc2에서 일하기 위해 수락된 답변에서 플런커를 고쳤습니다.멋지지 않아요, CDN 링크가 방금 끊겼어요.
'@angular/core': {
main: 'bundles/core.umd.js',
defaultExtension: 'js'
},
'@angular/compiler': {
main: 'bundles/compiler.umd.js',
defaultExtension: 'js'
},
'@angular/common': {
main: 'bundles/common.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser-dynamic': {
main: 'bundles/platform-browser-dynamic.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser': {
main: 'bundles/platform-browser.umd.js',
defaultExtension: 'js'
},
https://plnkr.co/edit/kVJvI1vkzrLZJeRFsZuv?p=preview
(rc5 호환) ng2-step을 사용할 준비가 된 구성 요소가 있습니다.Compiler
배선하기 를 제공합니다.
import { Directive , Input, OnInit, Compiler , ViewContainerRef } from '@angular/core';
import { StepsService } from './ng2-steps';
@Directive({
selector:'[ng2-step]'
})
export class StepDirective implements OnInit{
@Input('content') content:any;
@Input('index') index:string;
public instance;
constructor(
private compiler:Compiler,
private viewContainerRef:ViewContainerRef,
private sds:StepsService
){}
ngOnInit(){
//Magic!
this.compiler.compileComponentAsync(this.content).then((cmpFactory)=>{
const injector = this.viewContainerRef.injector;
this.viewContainerRef.createComponent(cmpFactory, 0, injector);
});
}
}
언급URL : https://stackoverflow.com/questions/36325212/dynamic-tabs-with-user-click-chosen-components
'programing' 카테고리의 다른 글
Lazy는 언제 사용해야 합니까? (0) | 2023.06.05 |
---|---|
이 예외를 어떻게 잡습니까? (0) | 2023.06.05 |
HTML/CSS에서 이미지를 그레이스케일로 변환 (0) | 2023.05.31 |
기본 안드로이드 빌드에 대응하지 못했습니다.SDK 위치를 찾을 수 없음 (0) | 2023.05.31 |
루비에서 두 Date 개체 사이의 일 수를 어떻게 찾을 수 있습니까? (0) | 2023.05.31 |