-1

I have copy paste the following directive

.directive("onlyNumber", function () {
    return {
        restrict: "A",
        link: function (scope, element, attr, ngModel) {
            element.bind('input', function () {
                var position = this.selectionStart - 1;

                //remove all but number and .
                var fixed = this.value.replace(/[^0-9\.]/g, '');  
                if (fixed.charAt(0) === '.')                  //can't start with .
                    fixed = fixed.slice(1);

                var pos = fixed.indexOf(".") + 1;
                if (pos >= 0)               //avoid more than one .
                    fixed = fixed.substr(0, pos) + fixed.slice(pos).replace('.', '');

                if (this.value !== fixed) {
                    this.value = fixed;
                    this.selectionStart = position;
                    this.selectionEnd = position;
                }
            });
        }
    };
})

The issue is that it's only working when I type and if I populate the value, it shows error required message.

The second issue is that, as I enter non-numeric key, it removes the value but length counter increase by one (i.e 1/20 instead of 0/20) and does not popup error. When I press submit, I am able to get the non-numeric value that I have entered.

@Edited

<ng-form name="nOtherFacilityForm" novalidate isolate-form flex="100" layout-padding layout layout-wrap>

                    <h2 class="md-title">Other Facilities</h2>
                    <div flex="100" class="animate-slide-up md-whiteframe-1dp white-bg" layout-padding layout layout-wrap>

                        <div flex="100" flex-gt-sm="25">
                            <md-input-container class="md-block">
                                <label>Almirah</label>
                                <input type="text" only-number  name="almirah" ng-model="LibraryEquipDetails.almirah" md-maxlength="20" maxlength="20"  required />
                                <div ng-messages="nOtherFacilityForm.almirah.$error">
                                    <div ng-message="required">Almirah is required.
                                    </div>
                                </div>
                            </md-input-container>
                        </div>
</ng-form>

and js side

$scope.saveInfo = function () {



            if($scope.nOtherFacilityForm.$invalid){
                angular.forEach($scope.nOtherFacilityForm.$error, function (field) {
                  angular.forEach(field, function(errorField){
                    errorField.$setTouched();
                  })
                });
            toastr.error("Please Fill All Mandatory Fields", "Alert!");
            return;
               }


        };

it pop up error and highlight the fields in red color , see image ERROR

When I type again, then everything is fine!!

Shahid Ghafoor
  • 2,991
  • 17
  • 68
  • 123

2 Answers2

2

Your directive doesn't update the ngModel, it just update the value.

to update your ngModel use:

ngModel.$setViewValue(fixed);

but you need to add: require: "?ngModel",

.directive("onlyNumber", function () {
    return {
        restrict: "A",
        require: "?ngModel",
        link: function (scope, element, attr, ngModel) {
            element.bind('input', function () {
                var position = this.selectionStart - 1;

                //remove all but number and .
                var fixed = this.value.replace(/[^0-9\.]/g, '');  
                if (fixed.charAt(0) === '.')                  //can't start with .
                    fixed = fixed.slice(1);

                var pos = fixed.indexOf(".") + 1;
                if (pos >= 0)               //avoid more than one .
                    fixed = fixed.substr(0, pos) + fixed.slice(pos).replace('.', '');

                if (this.value !== fixed) {
                    this.value = fixed;
                    this.selectionStart = position;
                    this.selectionEnd = position;
                    ngModel.$setViewValue(fixed);
                }
            });
        }
    };
})
Fetrarij
  • 7,176
  • 3
  • 27
  • 35
0
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { NgControl } from '@angular/forms';

@Directive({
    selector: 'input[numbersOnly]'
})
export class NumberDirective {

    constructor(private _el: ElementRef) { }

    @HostListener('input', ['$event']) onInputChange(event) {
        const initalValue = this._el.nativeElement.value;
        this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
        if (initalValue !== this._el.nativeElement.value) {
            event.stopPropagation();
        }
    }

}

and implement this component

<input type="text" class="form-control" name="zipcode" formControlName="zipcode" numbersOnly maxlength="5" />
Arvind
  • 74
  • 14
  • It's expected to provide some explanation for your answer to show how it solves the problem, please avoid posting only code answers. – Saeed Zhiany Oct 31 '19 at 08:48