0

I have two dropdowns,start time and end time, the first dropdown uses a time array, where time is selected, and then index of this time is used to slice , and array is made for the second dropdown. So that end time is always greater than start time.

Here I am trying to set default values when the submit button is clicked, but when I click the submit button then I am

  1. not getting the set Start time vale,it appears blank and
  2. getting end time value in the dropdown, but the drop down value array also shows time values less than the start time as well.

template

   Start at:
                <select
                [(ngModel)]="time1"
                (change)="onSelect($event.target.value)"   id="fTime">
                 <option value="0" selected>Select</option>
                  <option  [value]="i" *ngFor="let type of startTimeArray; let i = index">
                    {{type}}
                  </option>
               </select>
               End at:
              <select 
               [(ngModel)]="time2"
               id="tTime">
                 <option value="0" selected>Select</option>
                  <option [value]="type" *ngFor="let type of tempEndTimeArray">
                    {{type}}
                  </option>
              </select>


<div><button   (click)="submit()">click</button></div>

TS

import { Component } from "@angular/core";
import { FormGroup, FormArray, FormBuilder, FormControl } from "@angular/forms";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  forTableArray: any = [];
  time1:any=[];
  time2:any=[];
  startTimeArray:any=["07:00 AM","08:00 AM", "09:00 AM", "10:00 AM", "11:00 AM", "12:00 PM",  "1:00 PM",  "2:00 PM", "3:00 PM",  "4:00 PM", "5:00 PM",  "6:00 PM", "7:00 PM", "8:00 PM"];
  endTimeArray:any=["07:00 AM","08:00 AM", "09:00 AM", "10:00 AM", "11:00 AM", "12:00 PM",  "1:00 PM",  "2:00 PM", "3:00 PM",  "4:00 PM", "5:00 PM",  "6:00 PM", "7:00 PM", "8:00 PM"];
  public tempEndTimeArray: Array<any>;

  public enableEndTime: boolean = true;
  submit(){
this.time1="";
this.time2="";
this.tempEndTimeArray =this.startTimeArray;
this.time1="7:00 AM";
this.time2="5:00 PM";
  }
public onSelect(val){
  console.log(val)
  let index = parseInt(val) + 1;
  console.log(index)
   this.tempEndTimeArray = this.endTimeArray.slice(index);

}
  convertTime12to24(time12h) {
    const [time, modifier] = time12h.split(" ");
    let [hours, minutes] = time.split(":");
    if (hours === "12") {
      hours = "00";
    }
    if (modifier === "PM") {
      hours = parseInt(hours, 10) + 12;
    }
    return `${hours}:${minutes}`;
  }
}

Apart from that I am not able to get selected time value in my console, example if 01:00 PM is selected from the dropdown, I want it to display in the console, instead I am getting index value(as I have set [value]= i, in my html select dropdown, so that i can use slice for time)

https://stackblitz.com/edit/angular-r2sv3k

2 Answers 2

2

You have a few issues. Instead of detailing them individually, I will show you my version of your code and describe what I have done.

component.html

Start at:
<select [(ngModel)]="time1" (ngModelChange)="onTime1Change()">
  <option [ngValue]="-1">Select</option>
  <option  [ngValue]="i" *ngFor="let time of startTimes; let i = index">
    {{time}}
  </option>
</select>

End at:
<select [(ngModel)]="time2">
  <option [ngValue]="-1">Select</option>
  <option [ngValue]="i" *ngFor="let time of endTimes let i = index">
    {{time}}
  </option>
</select>

In the HTML, I am using [ngValue] to bind option values instead of [value]. [ngValue] binds the value itself, whereas [value] always uses the string representation. You want to use the index as the option values (a number), so should use [ngValue].

Also, I am using a value of -1 for the placeholder option. This is to avoid a clash between Select and the first item in the array.

Because you are using [(ngModel)], you can use (ngModelChange) to detect value changes. And because you are using two-way binding, you don't need to pass the value to the event handler - the model has already been updated.

component.ts

time1 = -1;
time2 = -1;

startTimes = ["07:00 AM","08:00 AM", "09:00 AM", "10:00 AM", "11:00 AM", "12:00 PM",
  "1:00 PM",  "2:00 PM", "3:00 PM",  "4:00 PM", "5:00 PM",  "6:00 PM", "7:00 PM", "8:00 PM"];    
endTimes: string[];

ngOnInit() {
  this.endTimes = this.startTimes.slice();
}

onTime1Change() {
  if (this.startTimes.indexOf(this.endTimes[this.time2]) <= this.time1) {
    this.time2 = -1;
  }

  let sliceIndex;
  if (this.time1 >= 0) {
    sliceIndex = this.time1 + 1;
  }

  this.endTimes = this.startTimes.slice(sliceIndex);
}

time1 and time2 are being bound to the <select> fields, and so their data type should match the <option> value types. I am initialising them to -1 to allow Select to appear selected as default.

There is no need for an endTimeArray and tempEndTimeArray - you can always take a copy from the startTimeArray. I have also declared their correct data types. I am initialising endTimeArray in ngOnInit().

onTime1Change() is doing all of the heavy lifting here. It performs the following actions:

  1. Reset time2 if time2 <= time1. Remember that the endTimes may be a slice, so you have to find the original index of the time2 value in startTimes.

  2. Set the slice index if time1 has a value

  3. Set endTimes

DEMO: https://stackblitz.com/edit/angular-sae1jr

Sign up to request clarification or add additional context in comments.

1 Comment

@user1997 No problem. I would recommend refactoring your code to use pure dates, but I didn't want to go down that rabbit hole in my answer.
1

My solution, rethink your design

app.component.ts

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {

  public startDate: Date;
  public endDate: Date;

  public readonly availableDates: Date[] = [
      new Date(2020, 4, 13, 10),
      new Date(2020, 4, 13, 11),
      new Date(2020, 4, 13, 12),
      new Date(2020, 4, 13, 13),
      new Date(2020, 4, 13, 14),
      new Date(2020, 4, 13, 15),
    ];

  get availableEndDates() {
      if(this.startDate == undefined) return[];
      const timeStampStart = new Date(this.startDate).getTime();
      return this.availableDates.filter(d =>  {
        const timeStampEnd = new Date(d).getTime();
        return timeStampStart < timeStampEnd;
      });
  }

  public submit() {
      if(this.startDate == undefined) this.startDate = this.availableDates[0]
  }

}

app.component.html

Start at:
<select [(ngModel)]="startDate">
  <option [value]="undefined">No date selected</option> 
  <option [value]="date" *ngFor="let date of availableDates">
    {{date | date:'hh:mm aaaa'}}
  </option>
</select>

End at:
<select [(ngModel)]="endDate" [disabled]="startDate == undefined">
  <option [value]="undefined">No date selected</option> 
  <option [value]="date" *ngFor="let date of availableEndDates">
      {{date | date:'hh:mm aaaa'}}
  </option>
</select>

<button (click)="submit()">click</button>

2 Comments

Thank you for your answer, it works.But what if I had to print the value of selected time in my console, how to extract that
I assume you want to log the selected time on the validation (click the click button). so you can access to the class property startDate, a Date object which own some useful methods like .getHours(): console.log(this.startDate.getHours());

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.