0

I am creating a dynamic chart component. I want to create a common function in component level (not in service label) so that from the different component can share that common function with different service to get the different type of result set.

Can anyone help me, how to do that?

public fetchSearchRecords(value): void {
    this.dataDisplay = true;
    this.isLoading = true;
    if (value.from_date) {
      this.from_date = moment(value.from_date).format('YYYY-MM-DD');
    }
    if (value.to_date) {
      this.to_date = moment(value.to_date).format('YYYY-MM-DD');
    }
    if (value.select_duration) {
      this.select_duration = value.select_duration;
    } else {
      this.select_duration = '';
    }

    this.doughnutChartService
      .getEmployeeAttritionRecords(
        this.select_duration,
        this.from_date,
        this.to_date
      )
      .subscribe(
        result => {
            // console.log('result==',result);
            this.isLoading = false;          
            this.empBandAttritionRecords = result['employee_band'];
            this.clientAttritionRecords = result['client'];
            const empBandMgmtLabelIds = [];
            const empBandMgmtLabel = [];
            const empBandMgmtLabelData = [];
            const empBandMgmtAttritionCount = [];
            let empBandArray = result['employee_band'];
            let clientArray = result['client'];
            let costCenterArray = result['cost_center'];
            let unitArray = result['unit'];
            let subUnitArray = result['sub_unit'];
            let domainArray = result['domain'];

            // EMP BAND MGMT RECORDS
            for (empBandArray in result) {
                if (result.hasOwnProperty(empBandArray)) {
                    if (empBandArray === 'employee_band') {
                        // tslint:disable-next-line: forin
                        for (let innerKey in result[empBandArray]) {
                            empBandMgmtLabelIds.push(result[empBandArray][innerKey].id);
                            empBandMgmtAttritionCount.push(
                            result[empBandArray][innerKey].attritions
                          );
                            empBandMgmtLabel.push(
                                result[empBandArray][innerKey].employee_band
                            );
                            empBandMgmtLabelData.push(
                                result[empBandArray][innerKey].attrition_percentage
                            );                  
                        }
                    }
                }
            }
        },
        error => {
          this.error = true;
          this.errorMsg = 'Sorry! Some error happen';
        }
    );
}

in the html,

<div *ngIf="dataDisplay && !isLoading">
    <div class="row" *ngIf="!error">
        <div class="col-md-4">
            <div class="card">
                <div class="card-header card-header-icon card-header-rose">
                  <div class="card-icon">
                    <i class="material-icons">insert_chart</i>
                  </div>
                  <h4 class="card-title">Employee Band</h4>
                </div>
                <div class="card-body">
                  <app-commo-doughnut-chart
                    [doughnutChartLabels]="ChartLabelEmpBand"
                    [doughnutChartData]="ChartLabelDataEmpBand"
                    [chartFilter]="empBandFilter"
                    [labelIds]="ChartLabelIdEmpBand"
                    [attritionCount]="ChartLabelEmpBandAttritionCount"
                  ></app-commo-doughnut-chart>
                </div>
            </div>
        </div>
    </div>
</div>

Now this above 'fetchSearchRecords' function is showing records in one component page but there are multiple different pages which will display same format of chart data but with different service function.

I can paste this code to all the components with different service function and it will display the data but in this case, there is serious code redundancy which I want to avoid.

Can anybody please suggest me a better solution to achieve the desired out put.

Biplob
  • 75
  • 2
  • 11
  • It seems that sharing it using services would be a good solution. https://stackoverflow.com/questions/50589902/how-to-share-functions-between-components-in-angular – Luigi Rubino Jul 10 '19 at 08:00
  • If you need to share the same function with multiple components, you can have a parent component class with that function and extend that class in all other components that you need to use the same function. – Johna Jul 10 '19 at 08:13
  • Using the Service is a good solution, but you can Also create a Class and define your function inside this class, then you can extends your components from this class – ilyas shabi Jul 10 '19 at 08:57

1 Answers1

0

You can consider passing a function to your child component as @Input, example:

<hello [getData]="getName"></hello>

It is declared as such in the child component

@Input() getData: (param: string) => Observable<string>;

Note that in the parent component, we would need to define the function in arrow function for it to get the correct this context.

getName = (input: string) => {
  return of(input + this.append);
}

You can substitute of part to a HTTP call.

Full example: https://stackblitz.com/edit/angular-j876oc

Icycool
  • 7,099
  • 1
  • 25
  • 33