programing

사용자 클릭 선택 구성 요소가 있는 동적 탭

batch 2023. 5. 31. 18:32
반응형

사용자 클릭 선택 구성 요소가 있는 동적 탭

구성 요소가 직접(제목으로) 등록할 수 있는 탭 시스템을 설정하려고 합니다.첫 번째 탭은 받은 편지함과 같고, 사용자가 선택할 수 있는 작업/링크 항목이 많이 있습니다. 이러한 각 클릭은 클릭 한 번으로 새 구성 요소를 인스턴스화할 수 있어야 합니다.작업/링크는 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);
    }
}

질문:

  1. 받은 편지함에서 새(다른) 탭을 만드는 동적 목록을 만들려면 어떻게 해야 합니까?나는 약간 추측하고 있습니다.DynamicComponentBuilder사용하시겠습니까?
  2. 받은 편지함(클릭 시)에서 구성요소를 생성하여 탭으로 등록하고 표시하는 방법은 무엇입니까?제 생각엔ng-content하지만 어떻게 사용하는지에 대한 많은 정보를 찾을 수 없습니다.

편집: 명확히 하려는 시도입니다.

받은 편지함을 메일 받은 편지함으로 생각합니다.항목은 JSON으로 가져오고 여러 항목을 표시합니다.항목 중 하나를 클릭하면 해당 항목 작업 'type'으로 새 탭이 만들어집니다.그러면 유형이 구성 요소가 됩니다.

편집 2: 이미지.

갱신하다

Angular 5 StackBlitz 예제

갱신하다

ngComponentOutlet4.0.0-1987.3에 추가되었습니다.

갱신하다

있습니다.NgComponentOutlet비슷한 일을 하는 진행 중인 작업 https://github.com/angular/angular/pull/11235

RC.7

플런커 예제 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();
    }    
  }
}

플런커 예제 RC.4
플렁커 예제 베타.17

업데이트 - 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();
    }    
  }
}

플렁커 예제 베타.17

원래의

당신의 질문에서 당신의 요구사항이 무엇인지 완전히 확신할 수는 없지만, 저는 이것이 당신이 원하는 것을 해야 한다고 생각합니다.

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];
}

플런커 예제 베타.15(플런커를 기반으로 하지 않음)

요소에 할 수 방법도 ( 적으로생구요동전방있다습니법달도는)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

반응형