ব্যবহারকারী-ক্লিক নির্বাচিত উপাদান সহ গতিশীল ট্যাব


224

আমি এমন একটি ট্যাব সিস্টেম সেটআপ করার চেষ্টা করছি যা উপাদানগুলি তাদের (একটি শিরোনাম সহ) নিবন্ধন করতে দেয়। প্রথম ট্যাবটি একটি ইনবক্সের মতো, ব্যবহারকারীর জন্য বেছে নেওয়া প্রচুর পরিমাণে ক্রিয়া / লিঙ্ক আইটেম রয়েছে এবং এই ক্লিকগুলির প্রত্যেকটিতে ক্লিকের উপর একটি নতুন উপাদান ইনস্ট্যান্ট করতে সক্ষম হওয়া উচিত। ক্রিয়া / লিঙ্কগুলি JSON থেকে আসে।

ইনস্ট্যান্টিয়েটেড উপাদানটি নতুন ট্যাব হিসাবে নিজেকে নিবন্ধিত করবে।

আমি নিশ্চিত নই যে এটি 'সেরা' পদ্ধতির কিনা? এখনও অবধি, আমি দেখেছি এমন একমাত্র গাইড হ'ল স্থির ট্যাবগুলির জন্য, যা কোনও সাহায্য করে না।

এখনও অবধি, আমি কেবলমাত্র ট্যাব পরিষেবা পেয়েছি যা অ্যাপ্লিকেশন জুড়ে চলার জন্য মূলত বুটস্ট্র্যাপযুক্ত is এটি দেখতে এমন কিছু দেখাচ্ছে:

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 হিসাবে আনা হয় এবং এটি বেশ কয়েকটি আইটেম প্রদর্শন করে। একবার আইটেমগুলির মধ্যে একটিতে ক্লিক করা হলে, আইটেমগুলির ক্রিয়া 'প্রকার' দিয়ে একটি নতুন ট্যাব তৈরি করা হয়। টাইপটি তখন একটি উপাদান।

সম্পাদনা 2: চিত্র


ট্যাবগুলিতে প্রদর্শিত উপাদানগুলি যদি বিল্ড টাইম হিসাবে পরিচিত না হয়, তবে ডিসিএল হ'ল সঠিক পদ্ধতি।
গন্টার জ্যাচবাউয়ার

7
আমি আপনার প্রয়োজনীয়তা স্পষ্টভাবে বুঝতে পারছি না তাই হার্ড কোড / প্লঙ্কার ছাড়া কোনও কিছু আপনাকে বলি। এটি যদি আপনি কোথাও plnkr.co/edit/Ud1x10xee7BmtUaSAA2R?p= পূর্বরূপ (এটি প্রাসঙ্গিক কিনা তা আমি জানি না) সহায়তা করতে পারে তা দেখুন
মাইক্রোনিক্স

@ মাইক্রোনিক্স আমি মনে করি আপনি ভুল লিঙ্কটি পেয়েছেন
কুয়েল

ওহে! আপনি যা চেয়েছিলেন তা করার চেষ্টা করছি। এখনও অবধি আমি গতিশীল সামগ্রী সহ ট্যাবটি তৈরি করতে সক্ষম হয়েছি কিন্তু ট্যাব পরিবর্তন করা হয় যখন উপাদানটির অবস্থা স্থির রাখার একটি সন্তোষজনক উপায় খুঁজে পেলাম না (লোডযুক্ত উপাদানগুলি খুব আলাদা হতে পারে)। আপনি এটি পরিচালনা কিভাবে?
জিপিনানী

উত্তর:


267

হালনাগাদ

কৌণিক 5 স্ট্যাকব্লিটজ উদাহরণ

হালনাগাদ

ngComponentOutlet ৪.০.০-বিটা ৩-এ যুক্ত করা হয়েছিল

হালনাগাদ

এমন একটি NgComponentOutletকাজ চলছে যা https://github.com/angular/angular/pull/11235 এর মতো কিছু করে

RC.7

Plunker উদাহরণ 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 {}

এছাড়াও কৌণিক.ও ডায়ামমিক কম্পিউটারের লোডার দেখুন

পুরানো সংস্করণ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

এটি আবার Angular2 RC.5 এ পরিবর্তিত হয়েছে

আমি নীচের উদাহরণটি আপডেট করব তবে এটি ছুটির আগের দিন।

এই প্লাঙ্কার উদাহরণটি দেখায় যে কীভাবে গতিশীলভাবে আরসি 5 তে উপাদান তৈরি করা যায়

আপডেট - ViewContainerRef .createComp घटक () ব্যবহার করুন

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();
    }    
  }
}

প্লাঙ্কার উদাহরণ আরসি .৪
প্লাঙ্কার উদাহরণ বিটা .১7

আপডেট - লোডনেক্সটটোলোশন ব্যবহার করুন

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();
    }    
  }
}

প্লাঙ্কার উদাহরণ বিটা .১7

মূল

আপনার প্রয়োজনীয়তাগুলি কী তা আপনার প্রশ্ন থেকে সম্পূর্ণ নিশ্চিত নয় তবে আমি মনে করি এটি আপনার যা চান তা করা উচিত।

Tabsকম্পোনেন্ট পাস ধরনের একটি অ্যারের পায় এবং এটি অ্যারের মধ্যে প্রতিটি আইটেমের জন্য "ট্যাব" তৈরি করে।

@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-comp घटक- loader.html দেখুন


1
অবশ্যই, আপনার DclWrapperপ্রকৃত উদাহরণটি তৈরি করতে আপনাকে কেবল উপাদানগুলি টাইপ করতে হবে।
গন্টার জ্যাচবাউয়ার

1
@ জোসেফ আপনি ViewContainerRefব্যবহারের পরিবর্তে ইনজেক্ট করতে পারেন ViewChild, তারপরে <dcl-wrapper>নিজেই লক্ষ্য হয়ে ওঠে। উপাদানগুলিকে লক্ষ্যবস্তু হিসাবে ভাইবোন হিসাবে যুক্ত করা হয় এবং তাই <dcl-wrapper>এই উপায়ের বাইরে থাকবে ।
গন্টার জ্যাচবাউয়ার

1
প্রতিস্থাপন সমর্থিত নয়। আপনি টেমপ্লেটটি ''(খালি স্ট্রিং) change এ পরিবর্তন করতে পারেন এবং নির্মাণকারীকে পরিবর্তন করতে পারেন constructor(private target:ViewContainerRef) {}, তারপরে গতিশীলভাবে যুক্ত উপাদানগুলি ভাই-বোন হয়ে যায়<dcl-wrapper>
Günter Zöchbauer

1
আমি আরসি 4 ব্যবহার করছি এবং উদাহরণটি বেশ কার্যকর ছিল। কেবলমাত্র আমি যা উল্লেখ করতে চাইছিলাম তা হ'ল সঠিকভাবে কাজ করতে বাধ্য করার জন্য আমাকে নীচের কোডটি যুক্ত করতে হয়েছিল .c
রাজি

4
এনজিএফটারভিউআইনিট ব্যবহার করার সময় ডায়নামিক উপাদানটিতে অন্য একটি ডায়াইনমিক উপাদান ছিল যখন আমি একটি ত্রুটি পেয়েছি। পরিবর্তে এনজিএফটারকন্টেন্টআইনেটে পরিবর্তন করা হয়েছে এবং এখন এটি নেস্টেড ডায়নামিক উপাদানগুলির সাথে কাজ করছে
অ্যাব্রিস

20

আমি মন্তব্য করার জন্য যথেষ্ট শান্ত না। আমি আরসি 2-তে কাজ করার জন্য গৃহীত উত্তর থেকে প্লাঙ্কারটি ঠিক করেছি। অভিনব কিছু নয়, সিডিএন-এর লিঙ্কগুলি কেবল ভেঙে গেছে।

'@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


16

(rc5 সামঞ্জস্যপূর্ণ) এনজি 2-পদক্ষেপ ব্যবহারের জন্য প্রস্তুত উপাদান রয়েছে যা 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);
    });
  }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.