Validating three inputs that they should not be same - html

I am using Boostrap to validate my registration form and I want user to provide three user name which should not be same. Now I cant prevent submitting but the boostrap form still showing that input field is correct, how can I mark it to be invalid for user to know which part they wrong?
html
<form class="needs-validation" novalidate>
<h6 class="d-inline-block pt-3">Please enter 3 choices for login username:</h6>
<div class="col-md-12 mb-3">
<label for="sys_user_first" class="form-label">
First Choice
<i class="fa-solid fa-star-of-life required-field fa-xs"></i>
</label>
<input type="text" class="form-control" id="sys_user_first" required>
<div class="invalid-feedback">
Please fill in the first choice and three choices should not be same.
</div>
<label for="sys_user_second" class="form-label">
Second Choice
<i class="fa-solid fa-star-of-life required-field fa-xs"></i>
</label>
<input type="text" class="form-control" id="sys_user_second" required>
<div class="invalid-feedback">
Please fill in the second choice and three choices should not be same.
</div>
<label for="sys_user_third" class="form-label">
Third Choice
<i class="fa-solid fa-star-of-life required-field fa-xs"></i>
</label>
<input type="text" class="form-control" id="sys_user_third" required>
<div class="invalid-feedback">
Please fill in the third choice and three choices should not be same.
</div>
</div>
</form>
JS
form.addEventListener('submit', function (event) {
if (form.checkValidity() === false||$("#d_sys_user_first").val() === $("#sys_user_second").val() || $("#sys_user_first").val() === $("#sys_user_third").val() || $("#sys_user_second").val() === $("#sys_user_third").val()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);

Related

How to disable auto fill (autocomplete) in password field (chrome and firefox)

I have implemented 'change password' functionality and it has 'old password', 'new-password' and 'retype password' fields. All these passwords fields suggest some other user account's passwords as auto-complete fields.
How to disable autocomplete in password fields. (chrome version-83.0.4103.116, Firefox version-78.0.1)
I have tried the following, and put in both form and input fields.
autocomplete ="off"
autocomplete ="nope"
autocomplete ="false"
autocomplete ="new-password"
none of these are working.
my password input code as below
<div class="form-group col">
<label for="oldPassword">Old Password</label>
<input type="password" formControlName="oldPassword" class="form-control" [ngClass]="{ 'is-invalid': submittedupdatepassword && updatepassform.oldPassword.errors }" />
<div *ngIf="submittedupdatepassword && updatepassform.oldPassword.errors" class="invalid-feedback">
<div *ngIf="updatepassform.oldPassword.errors.required">old password is required</div>
</div>
</div>
<form [formGroup]="updatepasswordform" (ngSubmit)="updatePassword()">
<div class="form-row">
<div class="form-group col">
<label for="oldPassword">Old Password</label>
<input type="password" formControlName="oldPassword" class="form-control" [ngClass]="{ 'is-invalid': submittedupdatepassword && updatepassform.oldPassword.errors }" />
<div *ngIf="submittedupdatepassword && updatepassform.oldPassword.errors" class="invalid-feedback">
<div *ngIf="updatepassform.oldPassword.errors.required">old password is required</div>
</div>
</div>
<div class="form-group col">
</div>
</div>
<div class="form-row">
<div class="form-group col">
<label for="newPassword">New Password</label>
<input type="password" formControlName="newPassword" class="form-control" [ngClass]="{ 'is-invalid': submittedupdatepassword && updatepassform.newPassword.errors }" />
<div *ngIf="submittedupdatepassword && updatepassform.newPassword.errors" class="invalid-feedback">
<div *ngIf="updatepassform.newPassword.errors.required">password is required</div>
<div *ngIf="updatepassform.newPassword.errors.minlength">password should contain minimum 8 characters</div>
<div *ngIf="updatepassform.newPassword.errors.pattern">* Minimum eight in length.<br />
* At least one upper and one lower case English letter.<br />
* At least one digit.<br />
* At least one special character [#?!#$%^&*-].<br /></div>
</div>
</div>
<div class="form-group col"></div>
</div>
<div class="form-row">
<div class="form-group col">
<label for="confirmPassword">Retype Password</label>
<input type="password" formControlName="confirmPassword" class="form-control" [ngClass]="{ 'is-invalid': submittedupdatepassword && updatepassform.confirmPassword.errors }" />
<div *ngIf="submittedupdatepassword && updatepassform.confirmPassword.errors" class="invalid-feedback">
<div *ngIf="updatepassform.confirmPassword.errors.required">Retype password is required</div>
</div>
</div>
<div class="form-group col"></div>
</div>
<div class="errMsg" >{{errorMsg}}</div>
<div class="successMsg" >{{successMsg}}</div><br>
<div class="form-group">
<button class="col-sm-2 update-btn btn btn-sm btn-rectangle btn-default text-case">
Upadate
</button>
</div>
</form>
Try autocomplete="new-password". This is recognized by modern browsers as a hint that they shouldn't offer to fill in password fields with saved passwords. (However, browsers will still offer to remember the password the user enters after they finish the form.)
Completely disconnecting a password field from browser's password managers is deliberately made impossible. This is because modern browsers prioritize security practices over developer flexibility, so security features like password managers are not something developers can opt out of. If you really need to have a password field that doesn't use password managers, you likely need to write some JavaScript to get a non-password text field to mask its input.
This Mozilla Developer Network article goes into more detail: https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion#the_autocomplete_attribute_and_login_fields
Please change
auto-complete ="off"
To
autocomplete="off"

Make input required upon clicking specific radio button

I need to make a specific input field required based on the choice of a specific radio button. I have tried ng-required but doesn't seem to work.
I want to make the phone number field required if one chooses the payment method4 with the model ng-model="selected_payment_method=CC
<form ng-submit="proceed_payment()" type="post" name="paymentForm" novalidate>
<div class="col s12">
<div class="col s12">
<input name="payment" ng-model="selected_cc_method" class="with-gap" id="payment4" type="radio"
value="CC" ng-click="selected_payment_method = 'CC'"/>
<label class="fund-project-payment-method-label" for="payment4">CC</label>
</div>
</div>
</div>
<div class="col s12 shipping-details">
<div class="fund-project-additional fund-project-personal-details">
Personal Details
</div>
<label for="email" class="fund-project-personal-details-label">Email</label>
<input placeholder="Email" id="email" type="email" ng-model="email" class="validate" required>
<!--
Phone Number & Name a required field as well
-->
<label for="display_name" class="fund-project-personal-details-label">Name</label>
<input placeholder="Name" id="display_name" ng-model="name" type="text"
class="validate" required>
<label for="phone_number" class="fund-project-personal-details-label">Phone Number</label>
<input placeholder="Phone Number" id="phone_number" type="text" ng-model="phone_number" ng-required="selected_payment_method === 'CC'">
<input placeholder="Your message." id="personal_message" ng-model="personal_message" type="text"
class="validate" maxlength="200">
<span class="personal-message-text">
This will be displayed on the campaign page.
</span>
</div>
<div class="col s12 right">
<button type="submit" class="waves-effect waves-light btn-large orange white-text proceed-payment"
disabled="selected_payment_method == undefined || paymentForm.$invalid || selected_reward_total_amount == 0">
Next: Pay
<i class="fa fa-chevron-right" ng-if="!proccess_payment_spinner"></i>
<div class="preloader-wrapper small active right payment-loader" ng-if="proccess_payment_spinner">
<div class="spinner-layer spinner-white-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div>
<div class="gap-patch">
<div class="circle"></div>
</div>
<div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
</button>
This is what I have done on the angular side to make sure payment is done.
What am I not doing right?
$scope.proceed_payment = function () {
$scope.proccess_payment_spinner = true;
if ($scope)
var payment_method = $('input:radio[name=payment]:checked').val();
if ($scope.selected_reward_details.limit_reward_amount &&
parseInt($scope.selected_reward_details.selected_quantity) > parseInt($scope.selected_reward_details.remaining_quantity)) {
$('#heading').html("Too many rewards!");
$('#message').html("Unfortunately the amount of rewards you've selected exceeds the number available.");
$('#error_modal').openModal();
return;
}
if (payment_method === "CC") {
ProjectPaymentService.initiateCCPayment(
$scope.project.id,
$scope.selected_reward_details.id,
$('#email').val(),
$('#display_name').val(),
$('#phone_number').val(),
$('#personal_message_display_name').val(),
$('#personal_message').val(),
parseInt($scope.selected_reward_details.selected_quantity),
parseFloat($scope.selected_reward_details.custom_amount),
parseFloat($scope.selected_reward_details.shipping_fee),
parseFloat($scope.selected_reward_details.reward_amount * $scope.selected_reward_details.selected_quantity),
parseFloat($scope.selected_reward_total_amount),
$('#address_1').val(),
$('#address_2').val(),
$('#country').val(),
$('#postcode').val(),
$('#city').val(),
$('#region').val()
).then(
function successHandler(data) {
$scope.proccess_payment_spinner = false;
var project_funding_id = angular.fromJson(data.data);
$location.path("mpesa_details/" + project_funding_id);
},
function errorHandler(data) {
$scope.proccess_payment_spinner = false;
console.log(angular.fromJson(data.data));
});
Radio type input does not need ng-click to set its value:
<input type="radio" name="payment" ng-model="selected_cc_method"
class="with-gap" id="payment4" value="CC" />
Now you can use selected_cc_method with ng-required:
<input placeholder="Phone Number" id="phone_number" type="text"
ng-model="phone_number" ng-required="selected_cc_method === 'CC'">
You can see here that when radio button is clicked, phone number input becomes required:
DEMO
You have two variables you are working with;
selected_cc_method
and
selected_payment_method
I would drop the ng-click and set the model of the radio and use the radio button value for the ng-required instead of trying to use another variable for this.
<input name="payment" ng-model="selected_payment_method" class="with-gap"
id="payment4" type="radio" value="CC"/>
<label class="fund-project-payment-method-label" for="payment4">CC</label>
<input placeholder="Phone Number" id="phone_number" type="text"
ng-model="phone_number"
ng-required="selected_payment_method === 'CC'">

Trigger action in a particular element of a collection inside an ng-repeat

I have an array of objects that is displayed using ng-repeat. In each of these objects there's a button that triggers an API request and toggles a flag in order to show a hidden div. Here's the HTML:
<div ng-repeat="tarjeta in tarjetas">
<label class="radio-inline">
<input type="radio" name="card" checked> {{tarjeta.brand}} ************{{tarjeta.digits}}
<button class="btn btn-dropdown" ng-click="openEditCard(); getEditableInfoCard(tarjeta.id)" ng-show="!editCard"></button>
<button class="btn btn-up" ng-click="openEditCard()" ng-show="editCard"></button>
</label>
<div ng-show="editCard">
<input type="text" name="nombre" placeholder="Nombre en la tarjeta:" class="form-control" ng-model="editableInfo.name" required>
<p ng-show="validaUpdateName">Dato incorrecto</p>
<div style="float: left; margin-right: 15px;">
<input type="text" name="expM" placeholder="Expiración (MM):" maxlength="2" class="form-control" ng-model="editableInfo.exp_month" required>
<p ng-show="validaUpdateMM">Dato incorrecto</p>
</div>
<label class="dash">
/
</label>
<div style="float: left;">
<input type="text" name="expY" placeholder="Expiración (YYYY):" maxlength="2" class="form-control" ng-model="editableInfo.exp_year" required>
<p ng-show="validaUpdateYY">Dato incorrecto</p>
</div>
<input type="text" name="direccion" placeholder="Dirección de la tarjeta:" class="form-control" required>
<br>
<br>
<br>
<div style="float: right;">
<button class="btn btn-primary" ng-click="updateCard(tarjeta)">Guardar cambios</button>
<button class="btn btn-trash"></button>
</div>
</div>
The problem is that when I click the button on a single element, the action is triggered for every element of the array. I think this is quite simple to solve but I'm a beginner using Angular and can't figure out what the problem is. I already tried tracking by $index. This is driving me crazy any help is welcome.
It really hasn't much to do with angular. Only with logic.
You're using single boolean editCard, and based on that boolean, you're supposed to know which cards should be opened, and which ones should not be. That can't possibly work. A single boolean can't store that amount of information. Only true or false.
Instead, you need, for each card to know if it is opened or not. So each card should have its own boolean flag:
<div ng-repeat="tarjeta in tarjetas">
<button ng-click="tarjeta.edited = true" ...></button>
<button ng-click="tarjeta.edited = false" ...></button>
<div ng-if="tarjeta.edited">
...
</div>
</div>
And if only one card is supposed to be opened at a time, thenwhat you need to know is which of the card is opened. Again, a boolean can't store that information. So you'd need
<div ng-repeat="tarjeta in tarjetas">
<button ng-click="edit(tarjeta)" ...></button>
<button ng-click="edit(null)" ...></button>
<div ng-if="tarjeta === editedTarjeta">
...
</div>
</div>
and in the controller:
$scope.editedTarjeta = null;
$scope.edit = function(tarjeta) {
$scope.editedTarjeta = tarjeta;
};

How to hide the message after hidden property is applied in angular2

I have this piece of code in my html file.
<div class="form-group"
[ngClass]="{'has-error': (countryVar.touched || countryVar.dirty) && !countryVar.valid }">
<label class="col-md-2 control-label" for="firstNameId">
Country
</label>
<div class="col-md-8">
<input class="form-control"
id="countryId"
type="text"
placeholder="Country (required)"
required
[(ngModel)]=customer.country
name="country"
#countryVar="ngModel" />
<span class="help-block" [hidden]="countryVar.touched">
Please enter your country.
</span>
</div>
</div>
Basically what I want to achieve is that after touched is true the message "Please enter your country " to be hidden.
How can I achieve that?

Angular form.$invalid submit button not working

So my validation is working the way it should with the exception of the buttons. I want them grayed out with opacity until all is valid and not sure if I have the ng-class set correctly and/or the ng-disabled set correctly or both.
The issue here is more per functionality. I have some fields that show when other fields dropdowns are selected to a particular item. For instance, "Age" is only shown is a particular option is selected whereas with all the other options, it does not show. I show my HTML and then my CSS below.
Yes, is a lengthy form, but hoping you all can help!
My form:
<form class="addClaim" name="claimForm" novalidate ng-submit="saveClaim(claimInfo)" data-ng-model="claimInfo">
<div class="form-group col-md-6 naviaInp">
<label for="beneSelect">Select your benefit</label>
<select class="form-control" name="beneSelect" id="beneSelect" ng-model="benefit" ng-options="item.descr for item in claim" required>
<option value="">Please select a benefit....</option>
</select>
<input type="hidden" ng-model="claimInfo.benefitId" ng-change="{{ claimInfo.benefitId = benefit.id }}"/>
</div>
<div ng-show="claimForm.beneSelect.$dirty && claimForm.beneSelect.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div class="form-group col-md-8 naviaInp" ng-show="benefit.askSecIns == true" >
<label for="secInc">Do you have secondary insurance</label>
<div>
<label class="radio-inline"><input type="radio" name="optradioSecIns" data-ng-model="claimInfo.isSecIns" value="true">yes</label>
<label class="radio-inline"><input type="radio" name="optradioSecIns" data-ng-model="claimInfo.isSecIns" value="false">no</label>
</div>
</div>
<div class="checkbox form-group col-md-8 naviaInp" ng-show="benefit.askResidual == true">
<p>If you have a Health Care FSA, any residual amount not covered by the HRA will automatically be entered into the FSA. If you do not wish to have the residual amount entered into your Health Care FSA, please indicate </p>
<label><input type="checkbox" name="residualAmount" data-ng-value="true" ng-model="claimInfo.isNoResId">
<p>No, please do not enter residual amounts into my Health Care FSA</p>
</label>
</div>
<div class="form-group col-md-6 naviaInp" ng-show="benefit.expenseTypes != null">
<label for="beneTypeSelect">Select type of service</label>
<select class="form-control" name="expenseType" id="beneServiceSelect" ng-model="expense" ng-options="item.descr for item in benefit.expenseTypes" required>
<option value="">Please select a service....</option>
</select>
<input type="hidden" ng-model="claimInfo.expenseTypeId" ng-change="{{ claimInfo.expenseTypeId = expense.id }}" />
</div>
<div ng-show="claimForm.expenseType.$dirty && claimForm.expenseType.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div class="form-group naviaInp">
<label for="start">Date of Service</label>
<div>
<input type="text" class="form-control" name="startDate" id="start" placeholder="--/--/----" data-ng-model="claimInfo.fromDate" style="width: 200px;" required>
<span style="padding-left: 20px; padding-right: 20px;">To</span>
<input type="text" class="form-control" id="end" placeholder="--/--/---- (optional)" data-ng-model="claimInfo.toDate" style="width: 200px;">
</div>
</div>
<div ng-show="claimForm.startDate.$dirty && claimForm.startDate.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div class="form-group col-md-6 naviaInp">
<label for="providerName">Provider Name</label>
<input type="text" name="providerName" class="form-control " id="providerName" ng-maxlength="100" data-ng-model="claimInfo.provider" required>
</div>
<div ng-show="claimForm.providerName.$dirty && claimForm.providerName.$error.required" style="clear: both; margin-top: 8px;">
<p class="claimError" style="color: #ab2328;"><i class="fa fa-exclamation-circle"></i><span style="padding-left: 10px; font-size: 14px; margin-bottom:: 25px;">this is a required field</span></p>
</div>
<div ng-show="claimForm.providerName.$dirty && claimForm.providerName.$error.maxlength" class="errorContainer" style="clear: both; margin-top: 8px;">
<p class="claimError" style="color: #ab2328;"><i class="fa fa-exclamation-circle"></i><span style="padding-left: 10px; font-size: 14px; margin-bottom:: 25px;">must be less than 100 characters</span></p>
</div>
<div class="form-group col-md-6 naviaInp" ng-model="claimInfo.depId" ng-show="benefit.dependents != null">
<label for="beneTypeSelect">Select dependant</label>
<select class="form-control" name="depSelect" id="beneDepSelect" ng-model="dependent" ng-options="item.name for item in benefit.dependents" required>
<option value="">Please select a dependant....</option>
</select>
<input type="hidden" ng-model="claimInfo.depId" ng-change="{{ claimInfo.depId = dependent.id }}" required />
</div>
<div ng-show="claimForm.depSelect.$dirty && claimForm.depSelect.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div class="form-group col-md-6 naviaInp" name="forWhom" ng-show="benefit.dependents == null">
<label for="forWhom">For Whom</label>
<input type="text" class="form-control" id="forWhom" ng-maxlength="100" data-ng-model="claimInfo.who" required >
</div>
<div ng-show="claimForm.forWhom.$dirty && claimForm.forWhom.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div ng-show="claimForm.forWhom.$dirty && claimForm.forWhom.$error.maxlength" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>a maximum of 100 characters are allowed</span></p>
</div>
<div class="form-group col-md-4 naviaInp" name="age" ng-show="benefit.benefCode == 'DCFSA'">
<label for="age">Age</label>
<input type="text" class="form-control" id="age" data-ng-model="claimInfo.age" ng-maxlength="50" required>
</div>
<div ng-show="claimForm.age.$dirty && claimForm.age.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div ng-show="claimForm.age.$dirty && claimForm.age.$error.maxlength" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>a maximum of 50 characters are allowed</span></p>
</div>
<div class="form-group col-md-4 naviaInp">
<label for="claimAmount">Amount</label>
<input type="number" name="amount" class="form-control" id="claimAmount" data-ng-model="claimInfo.amount" required ng-pattern="/^\d{1,4}(\.\d{0,2})?$/">
</div>
<div ng-show="claimForm.amount.$dirty && claimForm.amount.$error.required" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>this is a required field</span></p>
</div>
<div ng-show="claimForm.amount.$dirty && claimForm.amount.$error.pattern" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>the amount must be between $0 and $10,000</span></p>
</div>
<div class="form-group col-md-8 naviaInp">
<label for="claimComment">Comments</label>
<textarea class="form-control" name="comment" rows="5" id="claimComment" placeholder="optional" ng-maxlength="500" data-ng-model="claimInfo.comments">
</textarea>
</div>
<div ng-show="claimForm.comment.$dirty && claimForm.comment.$error.maxlength" class="errorContainer">
<p class="claimError"><i class="fa fa-exclamation-circle"></i><span>a maximum of 500 characters are allowed</span></p>
</div>
<div class="fileArea col-md-8 naviaInp">
<div>
<p>Drag and drop or upload your documentation. Remember, we cannot review your claim without at least one piece of proper documentation for each claimed expense listed above. Be sure your documentation shows the date of service, type of service, and cost of service.</p>
</div>
<div ngf-drop ngf-select ng-model="files" class="drop-box"
ngf-drag-over-class="'dragover'" ngf-multiple="true" ngf-allow-dir="true"
accept="image/*,application/pdf"
ngf-pattern="'image/*,application/pdf'"><p>Drag and drop your documents here or click to search for your documents and upload</p></div>
<div ngf-no-file-drop><p>File Drag/Drop is not supported for this browser</p></div>
<div>
<p>Files:</p>
</div>
<div>
<ul>
<li ng-repeat="f in files" style="font:smaller">{{f.name}} {{f.$error}} {{f.$errorParam}} <a class="deleteHandle" ng-click="deleteFile($index)">×</a> </li>
</ul>
</div>
</div>
<div style="padding-bottom: 150px; clear: both;">
<div class="checkbox col-md-8">
<label><input type="checkbox" value="" ng-model="checked"><p>By checking this box, you agree to Navia's <a class="naviaLink" data-toggle = "modal" data-target = "#tcModal" >Terms and Conditions</a>.</p></label>
</div>
<div class="form-group" style="clear: both;">
<input type="button" class="naviaBtn naviaBlue" ng-show="editMode == true" ng-click="updateClaim(claimInfo)" value="+ update claim" ng-disabled="claimForm.$invalid" ng-class="{'disabled-class': claimForm.$invalid}">
<input type="button" class="naviaBtn naviaBlue" ng-show="editMode == false" ng-click="saveClaim()" value="+ add another claim" ng-disabled="claimForm.$invalid" ng-class="{'disabled-class': claimForm.$invalid}">
<input type="button" class="naviaBtn naviaBlue" ng-disabled="!checked && claimForm.$invalid" ng-show="editMode == false" ng-class="{'disabled-class': !checked}" ng-click="saveAllClaims()" value="submit claim(s)">
</div>
<div>
<input type="button" class="naviaBtn naviaRed" ng-click="cancel()" value="cancel">
</div>
<div data-ng-hide="message == ''" data-ng-class="(savedSuccessfully) ? 'alert alert-success' : 'alert alert-danger'">
{{message}}
</div>
</div>
</form>
I did abbreviate code as much as I thought I could but still show what I am doing.
And my CSS:
.disabled-class {
background-color: #999999;
opacity: .30;
}
.disabled-class:hover {
background-color: #999999;
opacity: .30;
}
input.ng-invalid.ng-dirty {
border: 1px solid red;
}
.errorContainer {
clear: both;
margin-top: 8px;
}
.claimError {
color: #ab2328;
}
.claimError > span {
padding-left: 10px;
font-size: 14px;
margin-bottom:: 25px;
}
.disabled {
background-color: #999999;
opacity: .30;
}
.disabled:hover {
background-color: #999999;
opacity: .30;
}
What should happen here is that the buttons are grayed and disabled until all required fields have input and that the input is within the parameters set.
The angular form has both validity and invalidity properties.
Actually, all angular form elements do, they are nestable and invalidity bubbles up. If an element is invalid, automatically all the ancestors up to the form itself have $invalid == true.
You can call the form by its name in the $scope and the properties are $valid, respectively $invalid.
Here's the relevant code for your form:
<form name="claimForm">
// your form logic here
<button type="submit" ng-disabled="claimForm.$invalid" />
</form>
UPDATE: If your form doesn't behave the way you want, you should debug it:
divide your form into fieldsets, according to the logic of your form
when each of your fieldset are valid, your form is valid
test each fieldset sepparately and add some divs to display the $valid or $invalid value of each fieldset until you sort it out
I also think you are adding an unnecessary level of complexity to your problem by using inline conditional logic at html level. I'd keep it in the controller, where it's a lot easier to follow and structure.
Whenever something doesn't behave the way you expect it to, console.log(it).
One more thing: once dirty, an element will stay $dirty regardless of being or not disabled, unless you call $setPristine() on it. So you should probably try to avoid using $dirty in yoru logic, it might produce unncecessary confusion.
Most times, value.length and/or $valid are enough to make forms work.