JohnK
JohnK

Reputation: 45

Pass value from parent to child component not working

I have a drop down list on my parent component and when a user select a value, I want to pass that value to the child to be passed in another method call to the database. The issue is my value in the child is always undefined.

parent HTML

<div>
   <div style="margin-bottom: 20px;">
    <kendo-label [for]="reportList" text="Report:" style="margin-right: 10px;margin-bottom: 20px;"></kendo-label>
    <kendo-dropdownlist #reportList
                        [data]="reportListData"
                        [defaultItem]=defaultSelection
                        textField="reportName"
                        valueField="url"
                        (selectionChange)="reportDropDownChange($event)"
                        width="550px"></kendo-dropdownlist>
  </div>
  <div>
    <kendo-label [for]="usersubscriptionadmin" text="Distributor Admin:" *ngIf="isAdmin()" style="margin-right: 10px;"></kendo-label>
    <kendo-combobox #usersubscriptionadmin
                      [data]="userSubscriptionAdministrators"
                      [textField]="'userName'" 
                      [valueField]="'userId'" 
                      *ngIf="isAdmin()"
                      (selectionChange)="userSubscriptionAdminChange($event)"
                      style="width: 500px;"></kendo-combobox>
  </div>
     <div style="margin-top: 20px;">
       <router-outlet></router-outlet>
     </div>
</div>

parent.ts

import { Component, OnInit } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';

import {Notifications} from './../core/notifications/notifications';
import {UserService} from './../user/user.service';

import {ReportListModel} from './../user/models/report-list-model';
import { UserSubscriptionAdministratorModel } from '../user/models/user_subscription_administrator_model';

@Component({
  selector: 'app-reports-main',
  templateUrl: './reports-main.component.html',
  styleUrls: ['./reports-main.component.scss']
})
export class ReportsMainComponent implements OnInit {

  public reportListData: ReportListModel[] = [{reportName: "Subscription Invoice Summary", url: "reports/invoice-report"},
                                              {reportName: "Subscription Invoice Details", url: "reports/invoice-detail"},
                                              {reportName: "Admin Report", url: "reports/admin-report"}];

  public defaultSelection: ReportListModel = {reportName: 'Select a report', url:""};
  public userSubscriptionAdministrators: UserSubscriptionAdministratorModel[] = [];
  public href: any;
  public reportURL: string='';
  public selectedAdminUserId: number;
 

  constructor(private notifications: Notifications, private router: Router, private userService: UserService) {
    router.events.subscribe((event) =>{event instanceof NavigationEnd? this.href = event: null}); //get the page URL if there is a refresh        
   }

  ngOnInit() {
    //if the array is greater than one, then we know the user refreshed the page and already selected a report
    //so now set the report drop down
    this.reportURL = this.href.url.split('/')[2];
    //now set the default report selection to be the page URL
    if(this.reportURL != undefined)
    {
      console.log('setting default selection');
      this.defaultSelection = this.reportListData.find(x => x.url.includes(this.reportURL));
    }

    this.userService.GetUserSubscriptionAdministrators().subscribe(response => {
      response.forEach(a => {
        let admin = new UserSubscriptionAdministratorModel();
        admin.subscriptionId = a.subscriptionId;
        admin.userId = a.userId;
        admin.userName = a.firstName + ' ' + a.lastName;
        if (a.customerName !== null) {
          admin.userName += ' - ' + a.customerName;
        }
        if (a.ctsid !== 0) {
          admin.userName += ' (' + a.ctsid + ')';
        }
        this.userSubscriptionAdministrators.push(admin);
      });
    })
  }

  public reportDropDownChange($event)
  {
      if($event.url != ""){
        this.router.navigate([$event.url]);
      }
  }

  public isAdmin() {
    if (sessionStorage.getItem("UserType") == 'Administrator') {
      return true;
    } else {
      return false;
    }
  }

  public userSubscriptionAdminChange($event){
    console.log('Parent value change ' + $event.userId);
    this.selectedAdminUserId = $event.userId;
  }

}

Child HTML

form [formGroup]="form" class="k-form-horizontal">
<div style="display: inline-block;">
    <div style="display: inline-block; width: 175px;">
        <kendo-label [for]="fromDate" text="From:" style="padding-right: 6px;"></kendo-label> 
        <kendo-datepicker
            calendarType="classic"
            formControlName="fromDate"
            format="MM/yyyy"
            placeholder="MM/YYYY"
            #fromDate
            style="width: 125px;">
        </kendo-datepicker>
    </div>
    <div style="display: inline-block; width: 175px;">
        <kendo-label [for]="toDate" text="To:" style="padding-right: 6px;"></kendo-label>  
        <kendo-datepicker
            calendarType="classic"
            formControlName="toDate"
            format="MM/yyyy"
            placeholder="MM/YYYY"
            #toDate
            style="width: 125px;">
        </kendo-datepicker>
    </div>
    <div style="display: inline-block; width: 200px;">
        <kendo-label [for]="txtInvoiceNumber" text="Invoice Number:" style="padding-right: 6px;"></kendo-label>
        <kendo-textbox #txtInvoiceNumber formControlName="txtInvoiceNumber" style="width: 200px;"></kendo-textbox>
    </div>

    <div style="display: inline-block; width: 150px;padding-left: 6px;">
        <button type="submit" class="k-button k-primary" (click)="RunReport()" >Search</button>
    </div>
</div>

<div style="display: inline-block; padding-top: 5px;">
<kendo-grid
        [data]="gridData"
        [resizable]="true" 
        filterable="menu" 
        [sortable]="true" 
        [filter]="state.filter"
        [skip]="state.skip" 
        [sort]="state.sort" 
        [pageSize]="state.take"
        [pageable]="true"
        [height]="375" >
    <ng-template kendoGridToolbarTemplate>
        <button type="button" kendoGridExcelCommand icon="file-excel">Export to Excel</button>
    </ng-template>
    <kendo-grid-column field="invoiceDate" title="Date" width="100"></kendo-grid-column>
    <kendo-grid-column field="poNumber" title="PO Number" width="100"></kendo-grid-column>
    <kendo-grid-column field="invoiceNumber" title="Invoice Number" width="100"></kendo-grid-column>
    <kendo-grid-column field="invoiceAmount" title="Amount" width="100" format="{0:c}"></kendo-grid-column>
    <kendo-grid-excel fileName="InvoiceSummaryReport.xlsx" [fetchData]="excelExportData">
        <kendo-excelexport-column field="invoiceDate" title="Date"></kendo-excelexport-column>
        <kendo-excelexport-column field="ponumber" title="PO Number"></kendo-excelexport-column>
        <kendo-excelexport-column field="invoiceNumber" title="Invoice Number"></kendo-excelexport-column>
        <kendo-excelexport-column field="invoiceAmount" title="Amount"></kendo-excelexport-column>
    </kendo-grid-excel>
</kendo-grid>
</div>
</form>

childcomponent.ts

import { Component, Input, OnInit, } from '@angular/core';
import {FormControl, FormGroup} from '@angular/forms';
import {Router} from '@angular/router';
import {DatePipe} from '@angular/common';

import {addYears} from '@progress/kendo-date-math';
import {State, process} from '@progress/kendo-data-query'
import { ExcelExportData } from '@progress/kendo-angular-excel-export'

import {InvoiceSummaryReportModel} from '../models/invoice-summary-model';
import {ReportService} from '../report.service';
import { InvoiceSummarySearchModel } from '../models/invoice-summary-search-model';
import { Notifications } from '../../core/notifications/notifications';

@Component({
  selector: 'app-invoice-report',
  templateUrl: './invoice-report.component.html',
  styleUrls: ['./invoice-report.component.css']
})
export class InvoiceReportComponent implements OnInit {

  @Input('selectedAdminUserId') public parentSelectedAdminUserId: any;

public form: FormGroup;
public exportState: State;
public gridData: InvoiceSummaryReportModel[];
public exportData: any;
public tempDate:any;
public userId: number = Number(sessionStorage.getItem('UserId'));
public invoiceSearch: InvoiceSummarySearchModel;
public href: any;
public state: State = {
  take: 20
}

  constructor(private reportService: ReportService, 
              private router: Router, 
              private datepipe: DatePipe, 
              private notifications: Notifications) { 
    this.form = new FormGroup ({
      fromDate: new FormControl(addYears(new Date(), -1)),
      toDate: new FormControl(new Date()),
      txtInvoiceNumber: new FormControl()
    });

    this.excelExportData = this.excelExportData.bind(this);
  }

  ngOnInit() { }

  public RunReport(){
    this.invoiceSearch = new InvoiceSummarySearchModel();
    console.log('parent user id ' + this.parentSelectedAdminUserId);

      if(this.isAdmin())
      {
        this.invoiceSearch.userId =  this.parentSelectedAdminUserId;
      }
      else
      {
        this.invoiceSearch.userId = this.userId;
      }

      this.tempDate = this.datepipe.transform(this.form.controls.fromDate.value, 'MM/dd/yyyy').split("/");

      this.invoiceSearch.fromDateMonth =  parseInt(this.tempDate[0]);
      this.invoiceSearch.fromDateYear = parseInt(this.tempDate[2]);

      this.tempDate = this.datepipe.transform(this.form.controls.toDate.value, "MM/dd/yyyy").split("/");
      this.invoiceSearch.toDateMonth = parseInt(this.tempDate[0]);
      this.invoiceSearch.toDateYear = parseInt(this.tempDate[2]);
      this.invoiceSearch.invoiceNumber = this.form.controls.txtInvoiceNumber.value;

      this.reportService.GetInvoiceSummaryReport(this.invoiceSearch).subscribe(response => {
        if(response.message == "Success"){
            this.gridData = response.result;
        }
        else{
          this.notifications.error(response.message);
        }
      });
  }

  public excelExportData(): ExcelExportData {
    //set a filter for export if the user has filtered the result set.
    this.exportState = {
      filter: this.state.filter
    };
    //now set all the data to be exported.  Using gridData will only return the first page because the array is spliced to into 20 records.
    this.exportData = process<InvoiceSummaryReportModel>(this.gridData, this.exportState)
    const result: ExcelExportData = {
      data: this.exportData.data
    };
    return result;
  }

  isAdmin() {
    if (sessionStorage.getItem("UserType") == 'Administrator') {
      return true;
    } else {
      return false;
    }
  }
}

How do I set the parentSelectedAdminUserId in the child component?

Upvotes: 0

Views: 774

Answers (2)

Barremian
Barremian

Reputation: 31105

You aren't showing how the RunReport() function in the child component is triggered. But generally I could see the @Input variable is not being accessed dynamically. You could do one of the following

Option 1: @Input as a setter

Child component

export class InvoiceReportComponent implements OnInit {
    @Input() set parentSelectedAdminUserId(value: any) {
        console.log('parent user id:', value);
        // do something else
    }
}

Option 2: ngOnChanges hook

Child component

import { Component, OnInit, OnChanges, SimpleChanges, Input } from '@angular/core';

export class InvoiceReportComponent implements OnInit, OnChanges {
    @Input() parentSelectedAdminUserId: any

    ngOnChanges(changes: SimpleChanges) {
        if (
            !!changes && 
            !!changes.parentSelectedAdminUserId && 
            !!changes.parentSelectedAdminUserId.currentValue
        ) {
            console.log('parent user id:', this.parentSelectedAdminUserId);
            // do something else
        }
    }
}

Upvotes: 1

ataravati
ataravati

Reputation: 9145

Let's say the selector of your InvoiceReportComponent is invoice-report. Then, in the html of the parent component, you should pass that property like this:

<invoice-report [parentSelectedAdminUserId]="selectedAdminUserId" />

Upvotes: 0

Related Questions