In Angular 2, ngIF is not working when i am trying with two way binding - angularjs

I am working with Angular2 with two way binding concept [(ngModel)].I have form with my page and I have to validate the pristine state of the element. So for validation I have used ngIf to check the pristine state of the element. But the condition is not working. I need to check the pristine state for every model change. Below is my app.component.html page:
<form (ngSubmit)="angular2form(myAngular2Form.employeeDob)" [ngFormModel]="myAngular2Form">
<input type="text" class="form-control" id="employee" name="employee" [(ngModel)]="employeeDob" required />
<div *ngIf="employeeDob.pristine">
<p>Please enter the date</p>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
This is my component:
export class AppComponent {
employeeDob: String;
constructor(private myform: FormBuilder) {
this.employeeDob = '';
}
angular2form(date) {
alert("date submitted successfully");
}
}
Thanks for any suggestion

<input type="text" class="form-control" id="employee" name="employee" [(ngModel)]="employeeDob" #date="ngModel" required />
<div [hidden]="date.valid || date.pristine">
<p>Please enter the date</p>
</div>
straight outta documentation
https://angular.io/docs/ts/latest/guide/forms.html

pristine is a property of the Control not of the value.
You might want to use
<input #employeeDobCtrl="ngForm" type="text" class="form-control" id="employee" name="employee" [(ngModel)]="employeeDob" required />
<div *ngIf="employeeDobCtrl.pristine">
(for the old forms module)

pristine is true if the user has not interacted with the form yet. You probably want to check for dirty instead? You can also use the hidden tag and replace
<div *ngIf="employeeDob.pristine">
with:
<div [hidden]="employeeDob.pristine">

Related

parsley js - conditional required if checkbox checked

Is there an easy way with parsleyjs to make a field required depending on another field?
See my js fiddle here http://jsfiddle.net/marksteggles/wbhLq0t4/1/
<form data-parsley-validate="true">
<div class="form-group">
<label>
<input name="request_signature" type="checkbox" />Require signature</label>
<div class="request_signature_fields">
<textarea class="form-control required" name="signature_reason" rows="3"></textarea>
</div>
</div>
<input class="btn btn-success" name="commit" type="submit" value="Send" />
</form>
Minimally as of 2.2.0 you can create a custom validator:
window.Parsley.addValidator("requiredIf", {
validateString : function(value, requirement) {
if (jQuery(requirement).val()){
return !!value;
}
return true;
},
priority: 33
})
This gets applied in such a way:
<textarea
class="form-control required"
name="signature_reason"
rows="3"
data-parsley-validate-if-empty="true"
data-parsley-required-if="#my-field-to-check"
></textarea>
Explanation
data-parsley-required-if is the custom validator we just defined. It takes any arbitrary jQuery selector and if that field contains a non-falsy value it ensures that this field is not empty.
data-parsley-validate-if-empty is needed to ensure that the field is being validated at all, because Parsley does not validate empty non-required fields by default.
More data on custom validators here: http://parsleyjs.org/doc/index.html#custom
There is no easy way yet (see this and this).
You can either toggle the attribute required with Javascript, or listen to the right parsley events on one field and check the other field.
Just incase anyone else is trying to work this out. The best way does seem to be altering the required attribute then clearing the values.
I used this:
HTML:
<input id="checkbox-id" type="checkbox">
<div id="conditional-inputs" style="display:none;">
<input type="text" name="somename" />
<input type="text" name="othername" />
<input type="text" name="onemoreforluck" />
</div>
jQuery:
$("#checkbox-id").change(function() {
if(this.checked) {
$('#conditional-inputs').slideDown();
/* use .slideDown to display conditional input block */
$("#conditional-inputs :input").prop('required', true);
/* set required attribute on all inputs inside conditional area */
}
else{
$('#conditional-inputs').slideUp();
/* use .slideUp to hide conditional input block */
$("#conditional-inputs :input").prop('required', false).val('');
/* remove required attribute on all inputs and empty values of inputs */
}
})
I realise that this question was asked and answered in 2012, and is most likely related to the ParsleyJS v1, while the most recent version at the time of writing this is v2.2.0. However I had to do some work on an old form that used v1 and I found that conditionals are possible (with a little bit of jQuery). So here's to anyone who might still need this.
You can dynamically add and remove form elements and constraints (read: validation rules) using the following:
$('#form').parsley('addItem', '#input_id');
$('#form').parsley('removeItem', '#input_id');
$('#input_id').parsley('addConstraint', '{ required: true }');
$('#input_id').parsley('removeConstraint', 'required');
So using jQuery listeneners for when the checkbox changes we can execute this kind of code which will add the signature field as a required field. Here it is in action for the question.
< script src = "js/parsley-v1.js" > < /script>
<script>
$('#request_signature').on('click', function() {
if($(this).is(':selected')) {
$('#signature_form').parsley('addItem', '#signature_reason');
$('#signature_reason').parsley('addConstraint', { required: true });
} else {
$('#signature_reason').parsley('removeConstraint', 'required' });
$('#signature_form').parsley('removeItem', '#signature_reason');
}
});
</script >
<form id="signature_form" data-parsley-validate="true">
<div class="form-group">
<label>
<input id="request_signature" name="request_signature" type="checkbox" />Require signature</label>
<div class="request_signature_fields">
<textarea id="signature_reason" class="form-control" name="signature_reason" rows="3"></textarea>
</div>
</div>
<input class="btn btn-success" name="commit" type="submit" value="Send" />
</form>
You can also hide the parts that are not required anymore, or disable the fields that are not needed, and add [disabled] and :hidden to the excluded Parsley option.
{
excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], [disabled], :hidden',
}
NB: you don't need to hide each field, hiding a parent div is enough.
I found a good example that I forked here
➡️ http://jsfiddle.net/capripot/xoaLs4bt/
This should be possible with the great little Parsley addon plugin found here: http://themonk.github.io/parsely-conditions/
I found the shortest method -
$('input[type=radio][name=nlcsu]').change(function() {
// I am checking for a Radio button
if (this.value == 1) {
$("#nlcsu_post").attr('required', '1');
$("#nlcsu_year").attr('required', '1');
} else if (this.value == 0) {
$("#nlcsu_post").removeAttr('required');
$("#nlcsu_year").removeAttr('required');
}
});

Cannot reset form

I'm new to Angular and I have a simple retrieve password form with 1 email field and a submit button. I want to clear the form after the form has been submitted, but I can't seem to do it even after following tutorials/answers online.
I think it might be something I'm not understanding fundamentally, so if you could please let me know that would be great.
I'm using Angular v1.2.22
HTML (signin.forgotpassword.html)
<form name="forgotPasswordForm" class="form" role="form" ng-submit="forgetPasswordSubmit(forgetForm.email)" novalidate >
<div>
<label for="input-email" class="col-sm-2 control-label">Email</label>
<div>
<input name="email" ng-model="forgetForm.email" type="email" class="form-control" id="input-email" />
</div>
</div>
<div class="form-group">
<div>
<button name="submit" type="submit">Reset Password</button>
</div>
</div>
</form>
Angular (AuthController)
var forgetPasswordClear = function(){
var defaultForm = {
email: ''
};
// clear input
$scope.forgetForm = defaultForm; // Doesn't clear
// set form as pristine
$scope.forgotPasswordForm.$setPristine(); // Get Cannot read property '$setPristine' of undefined
};
$scope.forgetPasswordSubmit = function(email){
forgetPasswordClear();
};
----------EDIT----------
I'm not sure if it's because my form is sitting in a different ui view? My structure looks something like this:
HTML
<section data-ng-controller="AuthController">
<div data-ui-view>
Some content in there originally
<a ui-sref="signin.forgetpassword">Click here to get password</a>
</div>
</section>
Ui router
.state('signin.forgotpassword', {
url: '/signup/forgot-password',
templateUrl: 'modules/core/templates/signin.forgotpassword.html'
})
You set the wrong model:
Your model is 'forgetForm'
<input name="email" ng-model="forgetForm.email" type="email" class="form-control" id="input-email" ng-pattern="/.+\#.+\..+/" autofocus required />
current:
$scope.forget = defaultForm;
should be:
$scope.forgetForm = defaultForm;
EDIT TO ADDRESS NEW PROBLEM
It's because this is a child scope.
You need to use event emitters and listeners.
$broadcast -- dispatches the event downwards to all child scopes,
$emit -- dispatches the event upwards through the scope hierarchy.
Read more here: Working with $scope.$emit and $scope.$on

Validating nested form in angular

Having this ordinary (name attribute is requred by server) form with angular and can't figured out how to make validations work. What should i put into ng-show="TODO"
http://jsfiddle.net/Xk3VB/7/
<div ng-app>
<form ng-init="variants = [{duration:10, price:100}, {duration:30, price:200}]">
<div ng-repeat="variant in variants" ng-form="variant_form">
<div>
<label>Duration:</label>
<input name="variants[{{$index}}][duration]" ng-model="variant.duration" required />
<span ng-show="TODO">Duration required</span>
</div>
<div>
<label>Price:</label>
<input name="variants[{{$index}}][price]" ng-model="variant.price" />
<span ng-show="TODO">Price required</span>
</div>
</div>
</form>
</div>
ps: this is just piece of form, which is more complicated
Thanks
AngularJS relies on input names to expose validation errors.
Unfortunately, as of today it is not possible (without using a custom directive) to dynamically generate a name of an input. Indeed, checking input docs we can see that the name attribute accepts a string only.
Long story short you should rely on ng-form to validate dynamically created inputs. Something like :
<div ng-repeat="variant in variants" >
<ng-form name="innerForm">
<div>
<label>Duration:</label>
<input name="duration" ng-model="variant.duration" required />
<span ng-show="innerForm.duration.$error.required">Duration required</span>
</div>
<div>
<label>Price:</label>
<input name="price" ng-model="variant.price" required/>
<span ng-show="innerForm.price.$error.required">Price required</span>
</div>
</ng-form>
Working fiddle here
UPDATE : Base on your serverside requirement why not do something like that :
<input type="hidden" name="variants[{{$index}}][duration]" ng-model="variant.duration"/>
<input name="duration" ng-model="variant.duration" required />
The hidden input will be the one read by the server while the other one will be used to do the client side validation (later discarded by server). It s kind of an hack but should work.
PS : Be sure that your form is valid before actually submitting it. Can be done with ng-submit

Breaking a form between multiple tabs in angular breaks validation

I have an angular form spitted between several tabs with angular UI directive.
<form name="campaignForm" class="form-horizontal" novalidate >
<input type="text" name="title" class="input-xxlarge" placeholder="Campaign title" ng-model="campaign.title" required>
<span ng-show="campaignForm.title.$error.required" class="help-inline">
Required</span>
<tabset>
<tab>
</tab>
<input type="email" name="emailFrom" class="input-xsmall" placeholder="From email address" ng-model="campaign.info.emailFrom" required="" />
<span ng-show="campaignForm.emailFrom.$error.required" class="help-inline">
Required</span>
<tab>
<input type="text" name="emailSubject" class="input-xxlarge" ng-model="campaign.info.emailSubject" placeholder="Please enter email subject" required/>
<span ng-show="campaignForm.emailSubject.$error.required" class="help-inline">
Required</span>
</tab>
</tabset>
</form>
Please see my Plunker.
As you can see, only the input outside tabs directive works. The other inputs validation doesn't work because TABS create scopes. Any ideas how to solve this issue?
From the ngForm directive docs:
In Angular, forms can be nested. This means that the outer form is valid when all of the child forms are valid as well. However, browsers do not allow nesting of <form> elements, so Angular provides the ngForm directive, which behaves identically to form but can be nested.
This means that you can break your campaignForm form into sub-forms for each tab:
<form name="campaignForm" class="form-horizontal" novalidate >
<tabset>
<tab heading="first">
<div ng-form="emailForm">
<input type="email" name="emailFrom" class="input-xsmall" placeholder="From email address" ng-model="campaign.info.emailFrom" required />
<span ng-show="emailForm.emailFrom.$dirty && emailForm.emailFrom.$error.required" class="help-inline">
Required
</span>
</div>
</tab>
<tab heading="second">
<div ng-form="subjectForm">
<input type="text" name="emailSubject" class="input-xxlarge" ng-model="campaign.info.emailSubject" placeholder="Please enter email subject" required/>
<span ng-show="subjectForm.emailSubject.$dirty && subjectForm.emailSubject.$error.required" class="help-inline">
Required
</span>
</div>
</tab>
</tabset>
</form>
PLUNKER
This will circumvent the case where tabs directive (or any other directive that uses isolate scope) is breaking your ngFormController's scope.
Although it is old post, but i thought it would help someone
<tabset>
<tab class="nav-item_new_active" id="tab_content_PARAM1" title="{{ctrl.parameter.param_LABEL_1}}" template-url="partials/param/PARAM_1.html"></tab>
<tab class="nav-item_new" ng-id="tab_content_PARAM2" title="{{ctrl.parameter.param_LABEL_2}}" template-url="partials/param/PARAM_2.html"></tab>
</tabset>
I added a nested controllers in PARAM_1.html and PARAM_2.html with form names as
firstForm and secondForm.
In the controller code of firstForm and secondForm i placed a watcher function as below
$scope.$watch('secondForm.$valid', function(newVal) {
//$scope.valid = newVal;
var isPristine = $scope.secondForm.$pristine;
var isDirty = $scope.secondForm.$dirty;
console.log('secondForm Form isDirty'+isDirty);
//console.log('firstForm isPristine '+isPristine);
if($scope.secondForm.$valid==true){
if(isPristine==true){
console.log('secondForm Form is PRISTINE now '+$scope.secondForm.$valid);
//CHECK IF DIRTY IS TRUE HERE
if(isDirty==true){
console.log('secondForm Form is isDirty TRUE NOW>>DECREMENT');
}
} else {
//
isFormValidated = true;
console.log('secondForm IS COMPLETED NOW'+$scope.secondForm.$valid);
$scope.setValidationCount();
}
//console.log('secondForm Form is valid now '+$scope.secondForm.$valid);
} else {
//HERE IS THE PLACE
if(isFormValidated==true){
isFormValidated = false;
console.log('secondForm INVALIDATING FORM NOW');
$scope.decrementValidationCount();
}
}
Above piece of code is placed in nested controller for firstForm and secondForm. This piece can detect if form has been validated or not. It informs main form (myForm).
With this you can control the enable and disable or buttons on main form till all the sub forms are validated successfully.
Note : setValidationCount and decrementValidationCount are two methods in main controller which controls the enabling and disabling of BUTTONS on main form.

Angular JS Forms submit not sending model data

In the following example, message is undefined when I display it in the controller after the event is fired. Why?
<form>
<input type="text" ng-model="message.Title" />
<textarea ng-model="message.Content"></textarea>
<input type="submit" value="Send Message" ng-click="sendMessage(message)" />
</form>
Controller:
$scope.sendMessage = function(message) {
console.log(message);
}
My code seems identical to the documentation here except my controller manages the entire "page" not just the form.
Wow nevermind, apparently when you submit with blank values it doesn't even create the object.
I see you've found your problem, but I'd like to propose a solution to prevent your problem anyway:
<form name="messageForm" ng-submit="sendMessage(message)">
<input type="text" ng-model="message.Title" required/>
<span ng-show="messageForm.title.$error.required && messageForm.title.$dirty">required</span><br/>
<textarea ng-model="message.Content"></textarea>
<input type="submit" value="Send Message" ng-disabled="messageForm.$invalid" />
</form>
The above will make the Title required, display an error message, and disable your submit button if the form isn't valid.

Resources