0

I'm new to Angular. The closest question I found was:

  1. Validate html text input as it's typed : But they are using jquery

The actual project is way too sophisticated but I tried creating a minimal problem statement out of it. I want to validate a date as it is typed-in in real time. I'm using moment for validation. I created a custom validate() method which is called on (keydown)="triggerValidate()". Inside value() there are several checks:

  1. Format should be MM-DD-YYYY only.
  2. No date should be less than 1st Jan, 2015.
  3. No date should be above 31st Dec, 2020.

I've created a stckblitz also. But let me explain my logic.

There's a global varibale isDateValid: boolean which is set accordingly inside validate() method. If it is false then addInvalidStyle() will be called which will make the border red dynamically. And if it is true, then removeInvalidStyle() will be called which will remove then apply dynamic css and set the input field back to normal. Here's my code:

timeselector.component.html

<input [class.warning-border]="isApplied" [(ngModel)]="range" (keydown)="triggerValidate()"/>

timeselector.component.ts

import { ... } from '@angular/core';
import moment from 'moment';

@Component({
    ...
})
export class TimeselectorComponent {

      isDateValid: boolean=true;

      startingCalendarYear = 2015;
      endingCalendarYear = 2020;

      isApplied: boolean = false;

      range;

      triggerValidate() {
        this.validate(this.range);
      }

      validate(range: string) {
        this.isDateValid=true;
        const myDate = moment(range, 'MM-DD-YYYY', true);
        const lastDayOfCalendarYear = moment([this.endingCalendarYear]).endOf('year');
        const firstDayOfCalendarYear = moment([this.startingCalendarYear]).startOf('year');

        if (!myDate.isValid()) {
            this.isDateValid=false;
            this.addInvalidStyles();
        }
        if (myDate.isAfter(lastDayOfCalendarYear)) {
            this.isDateValid=false;
            this.addInvalidStyles();
        }
        if (myDate.isBefore(firstDayOfCalendarYear)) {
            this.isDateValid=false;
            this.addInvalidStyles();
        }
        if (this.isDateValid) {
            this.removeInvalidStyles();
        }
    }
    addInvalidStyles() {
        this.isApplied = true;
    }
    removeInvalidStyles() {
        this.isApplied = false;
    }
}

timeselector.component.css

.warning-border {
    border: 2.8px solid red;
    padding-top: 0.8px !important;
    padding-bottom: 3px !important;
}

Or you can directly see this stackblitz. My problem is that I have to press some key to validate my dates as I'm using keydown. I have to press enter to trigger even when the entered date is correct otherwise it will continue showing red alert. Please help me. Is this achievable or not without using form of any type.

Tanzeel
  • 4,174
  • 13
  • 57
  • 110
  • hi all, is anything wrong with this question. Is this even doable or am i wasting everyone's time. – Tanzeel Feb 13 '20 at 12:36
  • hi all, I tried this also: https://www.sitepoint.com/instant-validation/ – Tanzeel Feb 13 '20 at 12:42
  • I would suggest using `ReactiveForms` in Angular. Then you can use existing `Validators` or write your own and apply them to each "control" in your form, which will be validated as you type. – Chrillewoodz Feb 13 '20 at 12:47
  • @Chrillewoodz, Oh no. I'm sp sorry i cannot do that. this stackblitz is just an excerpt from the actual project. I cant make those changes. :-( – Tanzeel Feb 13 '20 at 12:50
  • @Chrillewoodz. Is it not possible with the existing code without touching html ? – Tanzeel Feb 13 '20 at 12:51
  • Why can't you make changes? It doesn't require that much in terms of changing the HTML. – Chrillewoodz Feb 13 '20 at 12:53
  • @Chrillewoodz. Sir I undertsnad, but that's not my code. This will have to go through code review by team lean and so much of drama they do. :-( – Tanzeel Feb 13 '20 at 12:54
  • @Chrillewoodz. Ok let's make it rective form for some time. but that form should not get submitted at any cost till i press Apply button manually (i've code for that also). – Tanzeel Feb 13 '20 at 12:55
  • @Peilonrayz. Ok I'll take care of my spellings. Sorry for that. And as far as code is concerned, there's nothing copyrighted. Its my own code. Even the variable names have been changes. I understand intellectual property rights. Thanks anyway. :-) – Tanzeel Feb 13 '20 at 13:08
  • @Tanzeel Thank you, your comments are _super_ easy to read now :) Sorry to have been a bother. Hope you have a good day. – Peilonrayz Feb 13 '20 at 13:10

1 Answers1

1

Hi I've read the comments, if you don't want to change the html code , to achieve your goal you have to add this:

import { Component, DoCheck, ViewChild } from "@angular/core";
import moment from "moment";

@Component({
  selector: "app-timeselector",
  templateUrl: "./timeselector.component.html",
  styleUrls: ["./timeselector.component.css"]
})
export class TimeselectorComponent implements DoCheck {

  ngDoCheck(): void {
    this.validate(this.range);
  }

Now you can delete (keydown)="triggerValidate()".

michel_98
  • 73
  • 6
  • This is working as expected but can you please explain this a little bit because I'll justify this to my tech lead. thanks in advance. – Tanzeel Mar 03 '20 at 05:38
  • 1
    The DoCheck() checks all changes in the component, so when you type it apllies the validation at the same time. – michel_98 Mar 05 '20 at 14:26