1

New to Angular and following a tutorial. I'm trying to trigger a dialog to open when I click on a row in a table. The table and the dialog are in two separate components. I used to have the dialog code in the same files as the table component code and then it worked fine, but now that they're separated out it doesn't. I can see from logging that the open() method in the dialog component is being triggered by the click in the table, but besides logging a message the dialog component doesn't do anything.

pix-table.component.ts

@Component({
  selector: 'pix-table-component',
  templateUrl: 'pix-table.component.html',
  styleUrls: ['pix-table.component.css'],
  providers: [PixSearchService, PixEditDialogComponent],
})
export class PixTableComponent implements IPix, OnInit, OnDestroy {
  columns = [
    'ID',
    'Network',
    'LOB',
    'HP Code',
    'Atypical',
    'TIN',
    'GNPI',
    'Org',
    'Business Unit Code',
    'National Contract',
    'National ContractType',
    'Contract Type',
    'Super Group',
    'Contract ID',
    'Amendment ID',
    'Contract Effective Date',
    'Contract Termination Date',
  ];

  rows: any;
  tableSize: TableSize = 'small';
  showHover = true;
  sticky: TableStickyType = 'horizontal';
  scrollType: TableScrollType = 'both';
  label = 'Payment Index Management';
  disabled = 'disabled';
  error = 'error';
  maxlength = 'maxlength';
  showCounter = false;

  elevation: CardElevation = 'medium';

  subscription!: Subscription;

  legacyConfigTrackerId!: number;
  contract!: IContract;
  audit!: IAudit;
  capitation!: ICapitation;
  changeRequest!: IChangeRequest;
  claimType!: string;
  deleted!: string;
  hnetAudit!: IHnetAudit;
  id!: string;
  noPayClassReason!: string;
  payClass!: string;
  product!: IProduct;
  provider!: IProvider;
  rateEscalator!: string;
  status!: string;
  selected: boolean = false;

  constructor(
    private pixSearchService: PixSearchService,
    private pixEditDialog: PixEditDialogComponent
  ) {}

  pixRecords: IPix[] = [];
  errorMessage: string = '';

  ngOnInit(): void {
    this.subscription = this.pixSearchService.getPixData().subscribe({
      next: (pixRecords) => {
        this.pixRecords = pixRecords;
      },
      error: (err: string) => {
        this.errorMessage = err;
      },
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  open(row: any) {
    console.log("row clicked");
    this.pixEditDialog.open(row);
  }
}

pix-table.component.html

<div kds-table-scroll [scrollType]="scrollType">
  <kds-table
    [size]="tableSize"
    [showHover]="showHover"
    [striped]="true"
    [sticky]="sticky"
  >
    <thead>
      <tr kds-table-row>
        <th kds-table-heading *ngFor="let col of columns">{{ col }}</th>
      </tr>
    </thead>
    <tbody>
      <tr
        kds-table-row
        *ngFor="let row of pixRecords"
        [selected]="row.selected"
        (click)="open(row)"       
      >
        <td kds-table-data>{{ row.legacyConfigTrackerId }}</td>
        <td kds-table-data>{{ row.product.network }}</td>
        <td kds-table-data>{{ row.product.lineOfBusiness }}</td>
        <td kds-table-data>{{ row.product.healthPlanCode }}</td>
        <td kds-table-data>{{ row.provider.isAtypical }}</td>
        <td kds-table-data>{{ row.provider.tin }}</td>
        <td kds-table-data>{{ row.provider.groupNpi }}</td>
        <td kds-table-data>{{ row.product.orgType }}</td>
        <td kds-table-data>{{ row.product.businessUnitCode }}</td>
        <td kds-table-data>{{ row.contract.isNational }}</td>
        <td kds-table-data>{{ row.contract.nationalContractType }}</td>
        <td kds-table-data>{{ row.contract.contractType }}</td>
        <td kds-table-data>{{ row.provider.superGroup }}</td>
        <td kds-table-data>{{ row.contract.emptorisNumber}}</td>
        <td kds-table-data>{{ row.contract.amendmentId }}</td>
        <td kds-table-data>{{ row.contract.effectiveDate }}</td>
        <td kds-table-data>{{ row.contract.terminationDate }}</td>
      </tr>
    </tbody>
  </kds-table>
</div>

pix-edit-dialog.component.ts

import { Component } from '@angular/core';
import {
  DialogSize,
  SelectSize,
  TextfieldSize,
} from '@dauntless/ui-kds-angular/types';
import { Subject } from 'rxjs';

@Component({
  selector: 'pix-edit-dialog',
  templateUrl: './pix-edit-dialog.component.html',
  styleUrls: ['./pix-edit-dialog.component.css'],
})
export class PixEditDialogComponent {
  textFieldSize: TextfieldSize = 'medium';
  yesNo = ['', 'Yes', 'No'];
  selectFieldSize: SelectSize = 'small';
  stateCodes = ['', 'AZ', 'AR', 'MO', 'TX'];
  lobs = ['', 'Ambetter', 'Medicaid', 'Medicare'];
  nationalContractTypes = [
    '',
    'National Contract Ancillary',
    'National Contract Hospital',
    'National Contract Transplant',
  ];
  contractTypes = [
    '',
    'AA-Ambulance. Air Transport',
    'AL-Ambulance. Land Transport',
    'AN-Ancillary',
    'AS-MCARE-AMBULATORY SURGICAL CENTER',
    'B1-MCARE-MENTAL HEALTH CLINIC',
    'B2-MCARE-ADULT MENTAL HEALTH',
    'B3-MCARE-METHADONE CLINIC',
  ];
  networks = [
    '',
    'AZ Health Net',
    'Exchange AR',
    'Exchange MO',
    'Medicaid MO',
    'TX Star Medicaid',
  ];

  healthPlanCodes = ['', 'AZ', 'AR', 'MO', 'TX'];
  orgs = ['', 'Behavioral', 'Medical'];
  businessUnitCodes = ['', 'AZ', 'AR', 'MO', 'TX'];

  selectedRecordId = 0;
  selectedRecordNetwork = '';
  selectedRecordLineOfBusiness = '';
  selectedRecordIsAtypical = '';
  selectedRecordTin = 0;
  selectedRecordGroupNpi = 0;
  selectedRecordHealthPlanCode = '';
  selectedRecordOrg = '';
  selectedRecordBusinessUnitCode = '';
  selectedRecordIsNational = '';
  selectedRecordNationalContractType = '';
  selectedRecordContractType = '';
  selectedRecordSuperGroup = '';
  selectedRecordContractEntity = '';
  selectedRecordContractId = '';
  selectedRecordAmendmentId = '';
  selectedRecordEffectiveDate = '';
  selectedRecordTerminationDate = '';
  tempEffDate = new Date();
  tempTermDate = new Date();

  open(row: any) {
    console.log("open method triggered");
    this.openDialog.next(row);
    this.selectedRecordId = row.legacyConfigTrackerId;
    this.selectedRecordNetwork = row.product.network;
    this.selectedRecordLineOfBusiness = row.product.lineOfBusiness;
    this.selectedRecordHealthPlanCode = row.product.healthPlanCode;
    this.selectedRecordIsAtypical = row.provider.isAtypical;
    this.selectedRecordTin = row.provider.tin;
    this.selectedRecordGroupNpi = row.provider.groupNpi;
    this.selectedRecordOrg = row.product.orgType;
    this.selectedRecordBusinessUnitCode = row.product.businessUnitCode;
    this.selectedRecordIsNational = row.contract.isNational;
    this.selectedRecordNationalContractType = row.contract.nationalContractType;
    this.selectedRecordContractType = row.contract.contractType;
    this.selectedRecordSuperGroup = row.provider.superGroup;
    // this.selectedRecordContractEntity = row.contractEntity;
    this.selectedRecordContractId = row.contract.emptorisNumber;
    this.selectedRecordAmendmentId = row.contract.amendmentId;
    this.selectedRecordEffectiveDate = row.contract.effectiveDate;
    
    if (this.selectedRecordEffectiveDate) {
      let tempEffDay = this.selectedRecordEffectiveDate.substring(3, 5);
      let tempEffMonth = this.selectedRecordEffectiveDate.substring(0, 2);
      let tempEffYear = this.selectedRecordEffectiveDate.substring(
        6,
        this.selectedRecordEffectiveDate.length + 1
      );
      this.selectedRecordEffectiveDate =
        tempEffYear + '-' + tempEffMonth + '-' + tempEffDay;
    }
    this.selectedRecordTerminationDate = row.contract.terminationDate;

    if (this.selectedRecordTerminationDate) {
      let tempTermDay = this.selectedRecordTerminationDate.substring(3, 5);
      let tempTermMonth = this.selectedRecordTerminationDate.substring(0, 2);
      let tempTermYear = this.selectedRecordTerminationDate.substring(
        6,
        this.selectedRecordTerminationDate.length + 1
      );
      this.selectedRecordTerminationDate =
        tempTermYear + '-' + tempTermMonth + '-' + tempTermDay;
    }
  }

  openDialog = new Subject();
  primaryActionText = 'Update';
  primaryActionClicked = () => {
    console.log(this.openDialog);
  };
  secondaryActionText = 'Cancel';
  size: DialogSize = 'large';
}

pix-edit-dialog.html

<div>
  <kds-dialog
    [openDialog]="openDialog"
    [primaryActionText]="primaryActionText"
    [secondaryActionText]="secondaryActionText"
    [size]="size"
    (primaryActionClicked)="primaryActionClicked()"
  >
    <!-- Header -->
    <kds-dialog-header>Edit Payment Index</kds-dialog-header>
    <kds-card-body>
        <ul class="demo-list">
          <li>
            <span class="demo-label">ID</span>
            <p id="edit-dialog-record-id">{{ selectedRecordId }}</p>
          </li>
          <li>
            <span class="demo-label">Network</span>
            <kds-select [size]="selectFieldSize">
              <select name="selectedNetwork" [value]="selectedRecordNetwork">
                <option *ngFor="let option of networks" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">Line of Business</span>
            <kds-select [size]="selectFieldSize" [disabled]=true>
              <select
                name="selectedLineOfBusiness"
                [value]="selectedRecordLineOfBusiness"
              >
              <option *ngFor="let option of lobs" [value]="option">
                {{ option }}
              </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">Health Plan Code</span>
            <kds-select [size]="selectFieldSize">
              <select
                name="selectedHpCode"
                [value]="selectedRecordHealthPlanCode"
              >
                <option *ngFor="let option of stateCodes" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">Atypical?</span>
            <kds-select [size]="selectFieldSize" >
              <select
                name="selectedAtypical"
                [value]="selectedRecordIsAtypical"
              >
                <option *ngFor="let option of yesNo" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">IRS #</span>
            <kds-textfield [size]="textFieldSize">
              <input type="text" [value]="selectedRecordTin" />
            </kds-textfield>
          </li>
          <li>
            <span class="demo-label">GNPI</span>
            <kds-textfield [size]="textFieldSize">
              <input type="text" [value]="selectedRecordGroupNpi" />
            </kds-textfield>
          </li>
          <li>
            <span class="demo-label">National Contract?</span>
            <kds-select [size]="selectFieldSize"
            >
              <select
                name="selectedNationalContract"
                [value]="selectedRecordIsNational"
              >
                <option *ngFor="let option of yesNo" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">National Contract Type</span>
            <kds-select [size]="selectFieldSize">
              <select
                name="selectedContractType"
                [value]="selectedRecordNationalContractType"
                [disabled]="selectedRecordIsNational == 'No'"
              >
                <option *ngFor="let option of nationalContractTypes" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">Contract Type</span>
            <kds-select [size]="selectFieldSize">
              <select
                name="selectedContractType"
                [value]="selectedRecordContractType"
              >
                <option *ngFor="let option of contractTypes" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">Super Group?</span>
            <kds-select [size]="selectFieldSize">
              <select
                name="selectedNetwork"
                [value]="selectedRecordSuperGroup"
              >
                <option *ngFor="let option of yesNo" [value]="option">
                  {{ option }}
                </option>
              </select>
            </kds-select>
          </li>
          <li>
            <span class="demo-label">Contract Entity</span>
            <kds-textfield [size]="textFieldSize">
              <input type="text" [value]="selectedRecordContractEntity" />
            </kds-textfield>
          </li>
          <li>
            <span class="demo-label">Contract ID</span>
            <kds-textfield [size]="textFieldSize">
              <input type="text" [value]="selectedRecordContractId" />
            </kds-textfield>
          </li>
          <li>
            <span class="demo-label">Amendment ID</span>
            <kds-textfield [size]="textFieldSize">
              <input type="text" [value]="selectedRecordAmendmentId" />
            </kds-textfield>
          </li>
          <li>
            <span class="demo-label">Contract Effective Date</span>
            <kds-textfield [size]="textFieldSize">
              <input type="date" [value]="selectedRecordEffectiveDate" />
            </kds-textfield>
          </li>
          <li>
            <span class="demo-label">Contract Termination Date</span>
            <kds-textfield [size]="textFieldSize">
              <input type="date" [value]="selectedRecordTerminationDate" />
            </kds-textfield>
          </li>
        </ul>
    </kds-card-body>
  </kds-dialog>
</div>

app.component.html

<pix-app-bar></pix-app-bar>
<pix-search-component></pix-search-component>
<pix-table-component></pix-table-component>
<pix-edit-dialog></pix-edit-dialog>
  • Did you inspect the html generated on browser after clicking a row, your dialog might be opening up but might have not width and height styles set properly (happens sometimes). Try to check if dialog html is present and then set height and width explicitly. – Syed Rafay May 20 '23 at 06:09

1 Answers1

0

The problem could be that the reference to PixEditDialogComponent that PixTableComponent has is not actually a reference to the PixEditDialogComponent instance that's on the page.

You're dependency-injecting PixEditDialogComponent into PixTableComponent, but those components are siblings, not parent-child, so PixEditDialogComponent is not in PixTableComponent's hierarchical dependency injection tree.

To reference the sibling PixEditDialogComponent instance from PixTableComponent, you could attach a template variable to <pix-edit-dialog> and pass that variable into <pix-table-component> as an Input(), like so:

<pix-table-component [pixEditDialog]="editDialogComponent"></pix-table-component> <--- pass template variable into Input pixEditDialog
<pix-edit-dialog #editDialogComponent></pix-edit-dialog> <--- add template variable editDialogComponent

In PixTableComponent, then, you would need to declare that @Input():

export class PixTableComponent implements IPix, OnInit, OnDestroy {
  @Input() pixEditDialog: PixEditDialogComponent

  // ...
}

and remove PixEditDialogComponent from the providers array and the dependency injection.

Here's a StackBlitz showing that approach to referencing a sibling component.

MikeJ
  • 2,179
  • 13
  • 16