rawrstar
rawrstar

Reputation: 165

Populating values in select dropdowns using ngmodel, angular 8

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

Upvotes: 0

Views: 4246

Answers (2)

Yug Damon
Yug Damon

Reputation: 501

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>

Upvotes: 1

Kurt Hamilton
Kurt Hamilton

Reputation: 13515

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

Upvotes: 2

Related Questions