Rhushikesh
Rhushikesh

Reputation: 3700

How to handle event in recursively nested component in angular2

I am working on functionality where I need to add component recursively and I want an event which will be triggered by the nested component at any level but it get handled on the Main parent component(appcomponent) which added that component

where is my recursively adding wts comp html

    <div class="panel panel-default panel-body" *ngIf="rules">
        <button class="btn btn-primary" (click)="addRule()">add rule</button>
        <button class="btn btn-primary" (click)="addGroup()">add group</button>
        <button class="btn btn-danger" (click)="removeGroup()" *ngIf="enableRemoveGroup">remove group</button>
        <div *ngIf="rules.groups">
<!-- adding itself if there is group -->
            <wts *ngFor="let group of rules.groups" [data]="group"></wts>
        </div>
        <rule *ngFor="let rule of rules.rules" [rule]="rule"></rule>
    </div>

wts component .ts

@Component({
    selector: 'wts',
    templateUrl: './wts.component.html',
    providers: [WtsServiceService],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class WTSComponent implements OnInit {
    rules: Group;
    enableRemoveGroup: boolean = false;
    @Output() removeGroupCB = new EventEmitter();
    @Input('data')
    set data(value) {
        if (value) {
            this.enableRemoveGroup = true;
        }
        this.rules = value || new Group();
    };
    constructor(private wtsServiceService: WtsServiceService) {
        this.rules = new Group();
    }
    private addGroup() {
        if (!this.rules.groups) {
            this.rules.groups = [];
        }
        this.rules.groups.push(new Group());
        console.log(this.rules);
    }
    private removeGroup() {
        delete this.rules;
    }
    private addRule() {
        this.rules.rules.push(new Rule());
    }
    ngOnInit() { }
}

In my comp I have object rules which contain the rules and groups, and group contains rule and group

here is my model

export class Rule {
    subjectType: string;
    valueType: string;
    subject: string;
    value: string;
    constructor(st = '', vt = '', s = '', v = '') {
        this.subjectType = st;
        this.valueType = vt;
        this.subject = s;
        this.value = v;
    }
}
export class Group {
    rules: Rule[];
    groups: Group[];
    constructor() {
        this.rules = [];
        this.rules.push(new Rule());
    }
};

If we have group withing group then it nested itself to form the UI. and we have rule component to list rules

here is my rule comp .ts

@Component({
  selector: 'rule',
  templateUrl: './rule.component.html',
  styleUrls: ['./rule.component.css'],
  providers: [WtsServiceService],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class RuleComponent implements OnInit {
  rule: Rule;
  @Input('rule')
  set Setrule(value) {
    this.rule = value;
  }
  constructor(private wtsServiceService: WtsServiceService) { }

  private triggerHanlder() {
    this.wtsServiceService.triggerCallBack();// to trigger appcomponent function
  }
}

here is my rule comp .html

<p *ngIf="rule">
  <button class="btn btn-danger" (click)="triggerHanlder()">trigger handler</button>
</p>

which will trigger an event when user select a valid rule and get handled by main component ie appcomponent

To do that I have created on service which returns observable which is subscribed on appcomponent and rule component call a function to trigger that event but its now working as expected.

here is my service

@Injectable()
export class WtsServiceService {
  resultSubject: ReplaySubject<any> = new ReplaySubject(1);
  constructor() { }
  public handleCallBack() {
    return this.resultSubject;
  }
  public triggerCallBack() {
    this.resultSubject.next({});
  }
}

here is my appcomponent

export class AppComponent {
  constructor( private _wtsServiceService: WtsServiceService) {

  }
  ngOnInit() {
    this._wtsServiceService.handleCallBack().subscribe(() => {
      console.log('parent function');//this should get execute when user click on trigger handler on rule comp
    })
  }
}

appcomp > wts > wts > wts >...> rule (here I have to emit an event and should get handled on appcomp. this rule compo may at any level)

Please help to find the workaround and suggest if there is any other better approach.

Upvotes: 0

Views: 980

Answers (1)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657168

I would make the root wts component a different component root-wts (can have the same template as the nested wts component, provide a service that that is injected to every wts and rule and also root-wts.

root-wts subscribes to an observable in this service wts (if applicable) and rule emit events using the observable in the shared service

Upvotes: 1

Related Questions