Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-validate input on SELECT element's change event

I am writing an AngularJS app and in this app there is a domain-management tool. When a domain is selected, I generate the domain-records in a table, letting the user edit each row. Since the fields are dynamically created, I use ng-form to enable validating each row individually, since they share the same name.

Each domain-record has a content field where an IP, CNAME, or such resides. I validate this field using a regex pattern generated from a function based on which record type is selected (A, CNAME, TXT, etc.).

The problem is that when I edit let's say, an A record, then change the record-type to CNAME, the form still appears valid since no new validation of the content-field has been performed. The only way for me to re-validate it is to start typing in the content field which then works fine.

Check images below:

I press edit on the A record and everything looks fine: enter image description here

I change the record type to CNAME and the form still appears valid even though the regex changed. When I change the type I want the content (1.2.3.4) to be re-validated since it's a new regex in place: enter image description here

I start typing in the content field and now the form correctly becomes invalid. I want this to happen when I change the record-type, not only when I start typing again: enter image description here

#Slim version of the template to give you an idea on whats going on
<form novalidate name="recordForm" class="css-form" ng-controller="EditRecordCtrl">

    <table>

        <tr ng-repeat="record in domain.data.0" class="gradeA">

            <td ng-init="startingTypeData = record.type" class="domains-td" ng-switch on="record.edit">
                <span ng-switch-default>{{record.type}}</span>
                <span ng-switch-when="true">
                    <select ng-change="domainRecordContentType(record.type)" ng-init="domainRecordContentType(record.type)" ng-model="record.type" ng-options="c for c in domainRecordTypes" class="span12">
                    </select>
                </span>
            </td>

            <td ng-init="startingContentData = record.content" class="domains-td validation-dropdown-error-parent" ng-switch on="record.edit">
                <span ng-switch-default>{{record.content}}</span>
                <span ng-switch-when="true">
                    <ng-form name="innercContentForm">
                        <span class="validation-dropdown-error" ng-show="innercContentForm.content.$error.pattern">
                            {{ 'RECORD_EDIT_FORM_RECORD_CONTENT_PATTERN_MSG' | translate }} ( {{ record.type }} )
                        </span>
                        <input type="text" ng-model="record.content" name="content" required class="span12 edit-record-input" ng-pattern="domainRecordContentRegex.0" required />
                    </ng-form>
                </span>
            </td>

        </tr>

    </table>

</form>

How can I re-validate the input field when I change the drop-down menu?

Plunker example: http://plnkr.co/edit/VAR5ho Note! Small bug not showing the A record in the first row. You can still test the issue tho as I did in the images above.

Update using Thomas custom directive

Before chaning dropdown enter image description here

After change first dropdown from A to CNAME all content fields are wiped enter image description here

Update save button

<button ng-disabled="recordForm.$invalid" ng-switch-when="true" ng-if="hideRecordType(record.type)" ng-click="recordForm.$valid && editRecord(record, domainId); record.edit=false; $parent.startingNameData=record.name; $parent.startingTypeData=record.type; $parent.startingContentData=record.content; $parent.startingTTLData=record.ttl; $parent.startingPrioData=record.prio" type="submit" class="btn btn-block btn-primary btn-icon" ><i></i>{{ 'DOMAINS_SAVE_BUTTON' | translate }}</button>

Last update.. odd behavior regarding compiled element

I press edit and it goes into my normal edit view enter image description here

I start typing a new IP address until it becomes valid enter image description here

If I make the content invalid after being valid once, like adding a dot the value gets wiped out. Why? enter image description here

Current directive based on Thomas code:

domainModule.directive('revalidate', function($compile) {
    return {
        restrict: 'A',
        link : function (scope, element, attrs) {
          scope.$watch(attrs.ngModel, function (v) {
              var reg = scope.$parent.domainRecordContentRegex[0];

              if(!$(element).parent().parent().next().find('ng-form').find('input').val().match(reg)){

                  $compile($(element).parent().parent().next().find('ng-form').children('input[name="content"]').removeClass('ng-valid-pattern'))(scope);
                  $compile($(element).parent().parent().next().find('ng-form').children('input[name="content"]').addClass('ng-invalid-pattern'))(scope);

              }

            });
        }
    };
});

I select the actual field now and change the class to make it invalid if the regex dont match. This way the Save button also gets invalid. This works when changing in the dropdown, but it corrupts the compiled element somehow.

like image 230
JoakimB Avatar asked Sep 14 '13 07:09

JoakimB


People also ask

How to validate inputs in HTML?

The simplest HTML validation feature is the required attribute. To make an input mandatory, add this attribute to the element. When this attribute is set, the element matches the :required UI pseudo-class and the form won't submit, displaying an error message on submission when the input is empty.

What is ng valid?

ng-valid is set if the form is valid. ng-invalid is set if the form is invalid. ng-pending is set if the form is pending. ng-pristine is set if the form is pristine. ng-dirty is set if the form is dirty.

What is ng-pristine?

ng-pristine: The ng-pristine class tells that the form has not been modified by the user. This returns true if the form has not been modified by the user. Return type: Return Boolean True if the form/input field is not modified by the user else it returns False.


1 Answers

To trigger validation, in ng-change of select set the value of input to its value. Change line 44 in your plunker to

<select ng-change="domainRecordContentType(record.type);innercContentForm.content.$setViewValue(innercContentForm.content.$viewValue)" ng-init="domainRecordContentType(record.type)" ng-model="record.type" ng-options="c for c in types">

Updated plunker http://plnkr.co/edit/D1AFHi

Credit: https://stackoverflow.com/a/17102401/69362

like image 123
Deepak N Avatar answered Oct 08 '22 11:10

Deepak N