I'm currently trying to change the default invalid text from form inputs using the code below. The way I'm trying to do it works if the text is static but in my case, the text must be dynamic so I have to put in some sort of prop/data value instead. This is because users will have the ability to toggle between English and Chinese text. I've tried using #invalid and :oninvalid but those don't seem to work. Would anyone be able to help me get through this issue?
<input
ref="firstInput1"
type="email"
v-model="email"
oninvalid="this.setCustomValidity('custom text on invalid')"
onchange="this.setCustomValidity('')"
:placeholder="Email"
required
/>
oninvalid and onchange are the two key components to making this work. Hopefully we can find out how to do this with dynamic text.
For change event in Vue input you should use #change (not onchange)
And I think this sample can help you to set vue validation on email
<div class="container" id="app">
<div :class="['input-group', isEmailValid()]">
<span class="input-group-addon" id="basic-addon1"><span class="fa fa-envelope"></span></span>
<input type="email" class="form-control" placeholder="Email Address" v-model="email" />
</div>
</div>
and
new Vue({
el: '#app',
data: {
email: '',
reg: /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,24}))$/
},
methods: {
isEmailValid: function() {
return (this.email == "")? "" : (this.reg.test(this.email)) ? 'has-success' : 'has-error';
}
}
});
Related
I am currently creating a form that has an unknown number of sensor fields within it. I've gotten the front end working beautifully. However, now I want to grab the user info out of those dynamically generated component fields and I can't figure out how. Here is where I'm generating the components:
{this.state.sensors.map((item, i) => (
<UpdateSensorInfo
key={i}
sensorName={item.sensorName}
sensorLowerLimit={item.sensorLowerLimit}
sensorUpperLimit={item.sensorUpperLimit}
/>
))}
And here is the actual component itself:
import React, { Component } from "react";
import "./updateSensorInfo.css";
class UpdateSensorInfo extends Component {
render() {
return (
<div>
<div className="sensorInfoFrame">
<div className="sensorFieldBody">
<label className="sensorTextFieldLabel">Sensor Name:</label>
<input
type="text"
name="text"
placeholder=""
className="sensorTextField"
defaultValue={this.props.sensorName}
required
/>
</div>
<div className="sensorFieldBody">
<label className="sensorTextFieldLabel">Sensor Upper Limit:</label>
<input
type="number"
name="text"
placeholder=""
className="sensorTextField"
defaultValue={this.props.sensorUpperLimit}
required
/>
</div>
<div className="sensorFieldBody">
<label className="sensorTextFieldLabel">Sensor Lower Limit:</label>
<input
type="number"
name="text"
placeholder=""
className="sensorTextField"
defaultValue={this.props.sensorLowerLimit}
required
/>
</div>
</div>
</div>
);
}
}
export default UpdateSensorInfo;
I would like to uniquely identify each text field within each generated component. How can I do this?
For anyone who has a similar situation, I have found a solution that works. There is a way to use the key that is created for each of the components within each component. use the following as an id or name for the input element:
id={`${this._reactInternalFiber.key}-additionalNameHere`}
This uses the key and will allow you to loop over the inputs within the components.
I need to show address every time it changes in Google Maps Autocomplete input.
The problem is that it does work only when I'm typing the text. When it shows options and I choose one of the addresses, it does not write the address.
<div class="col-6">
<div class="form-group form-group-default">
<label for="maps_autocomplete">Adresa</label>
<input type="text" id="maps_autocomplete" class="form-control" v-model="address">
</div>
</div>
address:[[address]]
<script>
var app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
address: '',
business_type_text: '',
},
methods: {}
});
</script>
How to make it react on choosing maps option?
EDIT
I tried to use change event:
<input type="text" id="maps_autocomplete" class="form-control" v-bind:value="address" v-on:change="address = $event.target.value">
Which works when I choose option, but it writes only the characters type inside the input, not the whole address.
So if I write:
"Wash"
And I select:
"Washington"
It shows just "address:Wash"
I have created a dynamic form based on data[fields] from JSON, but I need the form to be initially disabled, so that when we click on Edit then only form becomes editable.
Here is my code for form:
<div class="col-md-8 " [ngSwitch]="fieldInfo.dataTypeName">
<input *ngSwitchCase="'Text'"
class="form-control"
[(ngModel)]="pageInfoBeans.nameValueMap[fieldInfo.name]"
name="{{fieldInfo.name}}"
[required]="fieldInfo.preRequiredInd"
[maxLength]="fieldInfo.fieldSize">
<input *ngSwitchCase="'Email Address'"
type="email"
class="form-control"
[(ngModel)]="pageInfoBeans.nameValueMap[fieldInfo.name]"
name="{{fieldInfo.name}}"
[required]="fieldInfo.preRequiredInd"
[maxLength]="fieldInfo.fieldSize">
and in my component HTML which populates from above switch case :
<app-form class="" [fieldInfo]="fieldItem.fieldInfo" [pageInfoBeans]="pageInfoBeans"></app-form>
Initially set the form to disabled.
component.ts
showForm?:boolean = false;
component.html
<button (click)="showForm = !showForm">Edit</button>
<form *ngIf="showForm">
...form markup
</form>
You need to do something like this:
<button class='form-control' (click)='isEditable = !isEditable'>Edit Mode</button>
<div class="col-md-8 " *ngIf='isEditable' [ngSwitch]="fieldInfo.dataTypeName">
<input *ngSwitchCase="'Text'"
class="form-control"
[(ngModel)]="pageInfoBeans.nameValueMap[fieldInfo.name]"
name="{{fieldInfo.name}}"
[required]="fieldInfo.preRequiredInd"
[maxLength]="fieldInfo.fieldSize" />
<input *ngSwitchCase="'Email Address'"
type="email"
class="form-control"
[(ngModel)]="pageInfoBeans.nameValueMap[fieldInfo.name]"
name="{{fieldInfo.name}}"
[required]="fieldInfo.preRequiredInd"
[maxLength]="fieldInfo.fieldSize" />
</div>
[disabled]="!isEditable" where initialize isEditable = 'disabled' this could be added in both the text and email input fields.
Also in your edit button you can add a callback for click where you can set isEditable = ''.
#Directive({
selector : ["canbedisabled"]
})
export class Canbedisabled{
constructor(private el: ElementRef) {
}
#Input()
set blocked(blocked : boolean){
this.el.nativeElement.disabled = blocked;
}
}
<input formControlName="first" canbedisabled [blocked]="isDisabled">
You can solve it with a Directive. A directive named Canbedisabled and a property "blocked", for example. Write a setter for blocked and set it to nativelement.disabled property.
refer: https://github.com/angular/angular/issues/11271
This is my first time using AngularJS, and the form validation is making me question my sanity. You would think this would be the easy part, but no matter how many ways I've tried Googling, the only thing that works is if I set a flag inside my controller's submit if the form is invalid to set the error class. I've looked at similar problems here, but none of them helped, so please do not simply dismiss this as a potential duplicate. Everything else has been a fail.
In the example mark up below I have reduced my form down to just one element. Here is what I have observed:
Using only $error.required does work. The ng-class { 'has-error' :registerForm.firstName.$error.required} does outline the text box with the bootstrap has-ertror class, but this is on form load, which I do not want.
The <p> element with the error message will exhibit the same behavior, so I know that the message exists and is not malfored. It will also display if I only use $error.required. But as soon as I add && registerForm.$submitted ( or $isdirty or !notpristine ) the message will not display on form submit. There are no errors (have developers tools open in chrome) and will post to the web API with no problem and return ok 200 or 400 if I send bad params.
I can write validation code inside my controller, checking if the field has a value and setting a flag on $scope such as $scope.firstNameIsRequired and that will work fine setting ng-show="$scope.firstNameIsRequired", but that will remove testability.
So the problem definitely has to be with how I am adding this in the markup. But after a weekend spent googling I am at my wits end. The only other thing different is that I am using a span on a click element to submit the form instead of an input = submit, but the registerForm.$valid function is setting the correct value. Do I somehow need to trigger the form validation in that ng-click directive?
I am using angular.js v 1.4.8.
I do have angular ui which has it's own validate, but that shouldn't interfere with the basic validation.
Here is the simplified markup:
<form name="registerForm" class="form-group form-group-sm"
ng-controller="userAccountController" novalidate>
<div class="form-group"
ng-class="{ 'has-error' : registerForm.firstName.$error.required }">
<div><label>First Name</label> </div>
<input type="text" class="form-control" id="firstName" name="firstName" value=""
ng-model="firstName" placeholder="First Name" maxlength="100" required=""/>
<p ng-show="registerForm.firstName.$error.required && registerForm.$submitted"
class="alert alert-danger">First Name is required</p>
</div>
<div>
<span class="btn btn-default"
ng-click="submit(registerForm.$valid)">Register</span>
</div>
My controller code is
angular.module( "Application" ).controller( "userAccountController", [
"$scope", "userAccountService", function ( $scope, userAccountService)
{
$scope.hasErrors = false;
$scope.errorMessages = "";
$scope.emailExists = true;
$scope.clearErrors = function (){
$scope.hasErrors = false;
}
$scope.onSuccess = function ( response ) {
alert( "succeeded" );
}
$scope.submit = function (isValid) {
if ($scope.registerForm.$invalid)
return;
alert("isvalid");
$scope.clearErrors();
var userProfile = $scope.createUser();
userAccountService.registerUser(userProfile, $scope.onSuccess, $scope.onError);
}
$scope.createUser = function () {
return {
FirstName: $scope.firstName, LastName: $scope.lastName, Email: $scope.email,
Password: $scope.password, SendAlerts: $scope.sendAlerts
};
};
}
]);
Any help will be appreciated. I probably just need a second set of eyes here because I have been dealing with this on and off since late Friday.
in angular you want use the element.$valid to check wheter an model is valid or not - and you use element.$error.{type} to check for a specific validation error.
Keep in mind that the form.$submitted will only be set if the form is actually submitted - and if it has validationerrors it will not be submitted (and thus that flag is still false)
If you want to show errors only on submit you could use a button with type="submit" and bind to ng-click event - and use that to set a flag that the form has been validated. And handling the submit if the form is valid.
A short example with 2 textboxes, having required and minlength validation:
angular.module("myApp", [])
.controller("myFormController", function($scope) {
$scope.isValidated = false;
$scope.submit = function(myForm) {
$scope.isValidated = true;
if(myForm.$valid) {
console.log("SUCCESS!!");
}
};
});
.form-group {
margin: 10px;
padding: 10px;
}
.form-group.has-error {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="myApp" ng-controller="myFormController">
<form name="myForm">
<div class="form-group" ng-class="{'has-error': myForm.name.$invalid && isValidated}">
<span>Name:</span>
<input type="text" name="name" minlength="5" ng-model="name" required />
<span ng-if="myForm.name.$error.required && isValidated">Name is required</span>
<span ng-if="myForm.name.$error.minlength && isValidated">Length must be atleast 5 characters</span>
</div>
<div class="form-group" ng-class="{'has-error': myForm.email.$invalid && isValidated}">
<span>Email:</span>
<input type="text" name="email" minlength="5" ng-model="email" required />
<span ng-if="myForm.email.$error.required && isValidated">Email is required</span>
<span ng-if="myForm.email.$error.minlength && isValidated">Length must be atleast 5 characters</span>
</div>
<button type="submit" ng-click="submit(myForm)">Submit</button>
</form>
</div>
Having such form
<div ng-controller="FormController as f_ctrl">
<form ng-submit="f_ctrl.submit()" name="myForm">
<input type="text" ng-model="f_ctrl.user.username"
required
ng-minlength="4"/>
<input type="text" ng-model="f_ctrl.user.password"/>
<input type="submit" value="Submit" ng-disabled="myForm.$invalid">
</form>
</div>
and such controller
.controller('FormController', [function() {
var self = this;
self.submit = function() {
console.log('User submitted form with ' + self.user.username)
}
}]);
I have a problem: when page first loads it immediately shows red border on username field, even before I start typing anything.
I need to highlight invalid fields only after first submission. Can this be done using form.$invalid ?
You have to use $pristine for that. It is true when form controller is not changed. so when you change textbox data its comes false.
Small example for you.
<div class="form-group" ng-class="{ 'has-error' : userForm.password.$invalid && !userForm.password.$pristine }">
<input id="passAnime" type="password" name="password" ng-model="user.password" class="form-control input-md" placeholder="Password" tabindex="5" ng-maxlength="25" ng-minlength="6" required>
<span ng-show="userForm.password.$dirty && userForm.password.$invalid">
<p ng-show="userForm.password.$error.required" class="error-messages">
Your password is required.
</p>
<p ng-show="userForm.password.$error.minlength" class="error-messages">
Your password is too short. Minimum 6 chars.
</p>
<p ng-show="userForm.password.$error.maxlength" class="error-messages">
Your password is too long. Maximum 25 chars.
</p>
</span>
</div>
Angular has helpers that tell you if the form (or form field) is $dirty (user has typed something) or if the form is $touched (the blur event has been triggered on the input). See this demo.
I need to highlight invalid fields only after first submission.
Unfortunately, Angular doesn't support that. But you could implement it yourself rather easily:
Controller
function FormController() {
var vm = this;
vm.submitAttempted = false;
vm.submit = function(isValid) {
if (isValid) {
// do stuff
}
else {
vm.submitAttempted = true;
}
};
}
HTML
<div ng-app='app'>
<div ng-controller='FormController as vm'>
<form name='fooForm' ng-submit='vm.submit(fooForm.$valid)' novalidate>
<label>Username</label>
<input
name='username'
type='text'
ng-model='vm.user.username'
required
ng-minlength='4'
ng-class="{'invalid': vm.submitAttempted && fooForm.username.$invalid}">
<br /><br />
<button type='submit'>Submit</button>
</form>
</div>
</div>
CSS
.invalid {
border-color: red;
}
Demo
I have a problem: when page first loads it immediately shows red border on username field, even before I start typing anything.
That's probably because you have the following CSS class:
.ng-invalid {
border-color: red;
}
Angular will always apply the ng-invalid class to fields that are invalid, and there's nothing you could do about that. So if you don't always want invalid fields to have a red border, you can't use that class and you should do it in a way similar to what I proposed above.
Also, check out ngMessages.
You can disable the default styling on the input field that is adding the red border by default, by adding the following CSS:
input:required {
-moz-box-shadow: none;
box-shadow: none;
}
Then if you want to highlight the field when the form is submitted, you will need to ensure that the form and form fields have relevant name attributes. Doing this will allow you to check if the field is valid or not and apply a class to your text field when it is invalid:
<input type="text" name="username" ng-class="{ 'invalid-field' : f_ctrl.myForm.username.$invalid && !f_ctrl.myForm.username.$pristine }" required />
f_ctrl.myForm and f_ctrl.myform.username will have additional properties that you can use/check to determine if the form or fields are invalid or not, or if they have been modified at any point (e.g. f_ctrl.myform.username.$dirty). You should be able to view these properties on your page by adding the follow HTML:
<div>
<pre>{{f_ctrl.myForm | json}}</pre>
</div>
Or, you could output self.myForm to the console from your controller to view it's properties
console.log(self.myForm);