Tanzeel
Tanzeel

Reputation: 4998

How to treat same component as two different components inside same parent [Angular]

I've recently started working on Angular. I'm sorry if I'm asking a wrong question. I've created a stackblitz also. But please let me explain. I've created two custom components from the scratch. One is Timeselector and the other is Monthpicker. Inside Timeselector I'm calling Monthpicker twice. Where Monthpicker is just a collection of 3 input fields (one for arrow symbol in between and two for entering values) which will accept startRange and endRange as input in MM-DD-YYYY format only. Validation being handled by moment.

timeselector.component.html

Primary range:
<app-monthpicker></app-monthpicker>

Reference range:
<app-monthpicker></app-monthpicker>

<button (click)="onSubmit()">Submit</button>

monthpicker.component.html

<div class="wrapper">
  <input type="text" [(ngModel)]="startRange" placeholder="MM-DD-YYYY">
  <input type="text" value="{{arrowSymbol}}" readonly>
  <input type="text" [(ngModel)]="endRange" placeholder="MM-DD-YYYY">
</div>

monthpicker.component.ts

import { Component, OnInit } from '@angular/core';
import moment from 'moment';

@Component({
  ...
})
export class MonthpickerComponent implements OnInit {

  arrowSymbol = String.fromCharCode(parseInt('2794', 16));

  startRange: string;
  endRange: string;

  isRangeValid: boolean;

  dateErrors: Set<string>;

  constructor() { }

  ngOnInit() {
  }

  triggerValidate() {
    this.validate(this.startRange, this.endRange);
  }

  validate(sDate: string, eDate: string) {
    this.isRangeValid=true;
    this.dateErrors = new Set<string>();
    const fromDate = moment(sDate, 'MM-DD-YYYY', true);
    const toDate = moment(eDate, 'MM-DD-YYYY', true);
    if (!fromDate.isValid() || !toDate.isValid()) {
      this.dateErrors.add('Errors.DateIsNotValid');
      this.isRangeValid = false;
    }
    if (fromDate.isAfter(toDate)) {
      this.dateErrors.add('Errors.StartDateMoreThanEndDate');
      this.isRangeValid = false;
    }
    if (this.isRangeValid) {
      console.log("All good!");
      console.log("Primary range: "+this.startRange+" to "+this.endRange);
      console.log("Secondary range: "+this.startRange+" to "+this.endRange)
    }
    console.log(this.dateErrors);
  }
}

You can see I've bound the properties to startRange and endRange. I can bind only these two properties because Monthpicker component is one component being called twice. But I want all four values to be validated and printed on console viz. Primary range start and end dates and also for reference range start and end dates. How to create two instances of same component. I've checked this also:

  1. How to inject new instance of same component in Angular2

But I didn't understand that very well. Hope I was able to explain the problem statement. I'm afraid my entire implementation is wrong. Please help me.

Upvotes: 0

Views: 1612

Answers (1)

Jins Thomas Shaji
Jins Thomas Shaji

Reputation: 877

Instead of ViewChild, ViewChildren can be used for accessing multiple child components.

Then each child component in the parent component can be validated.

monthpicker.component.ts

Instead of using ViewChild:

@ViewChildren(MonthpickerComponent) 
monthpicker: MonthpickerComponent[];

Then on the onSubmit method:

onSubmit() {
  this.monthpicker.forEach(picker => {
    picker.triggerValidate();
  });
}

StackBlitz: https://stackblitz.com/edit/angular-zdt48j?file=src%2Fapp%2Ftimeselector%2Ftimeselector.component.ts

Upvotes: 1

Related Questions