I would like to get all errors from a form.
I tried to use the live example that came with Angular documentation, and I modified it adding required to the first field:
createForm() {
this.heroForm = this.fb.group({
name: ['', Validators.required],
secretLairs: this.fb.array([]),
power: '',
sidekick: ''
});
}
https://plnkr.co/edit/6b1paWOlKtXnDn1VVCyP
As you can see, if you empty the name field it triggers the required validator and control related to name field has an errors object... but errors property of myForm object is still null. Why?
Shouldn't it contain an object with all errors that are triggered by validators of the children controls?
So what does errors property stand for?
You would have to loop through the controls of the form and see if they contain errors one by one. And I think you can actually have validators on the group it self, the same way you would have validation on a single form control.
Related
Is it possible to add ignorable fields to Angular 2's reactive forms?
To simplify things, look at this Form:
this.form = new FormGroup({
subTasks: new FormArray([]),
});
Each subTask will be solved by the user and the solution is saved inside the FormArray.
Now in order to display the text of the different subTasks, I added a FormControl called "text" to each subTask. But when the user submits the form, I don't want the task text to be sent to the server along with the user input.
I know I could just not use it, or remove it programmatically before submitting, but I was wondering if there is a way to do it clean. Thanks!
What you could utilize is to disable the formfield text, which means that the field is not included in the form object, but you can still use it. Sample:
this.myForm = this.fb.group({
text: [{value:'text value', disabled: true}],
somethingElse: ['something else']
});
and in template:
<form [formGroup]="myForm">
<p>{{myForm.get('text').value}}</p>
<input formControlName="somethingElse">
</form>
If you want to inspect the whole form object, disabled fields included, you can use:
this.myForm.getRawValue();
Cross-Field Validation in Template Based Forms
Question: Is it possible to create some sort of validation context that spans multiple fields but does not modify the underlying model? If not, is there a better way to do what I'm doing?
Given a model like this and assuming that changing the model is not possible:
export interface IEvent {
location?: {
address: string;
city: string;
country: string;
};
onlineUrl?: string;
}
What is the best way to build a template-based form that will require either all of the location object (address, city, country) to be populated OR the onlineUrl to be populated?
Here is a working Plunk where I have the custom validation working but there are some challenges:
In order to match the model, we need an ngModelGroup around the location fields, but onlineUrl should not be inside that ngModelGroup since it is not part of the location object. Since onlineUrl is not inside the ngModelGroup, it's difficult to come up with a cohesive validation approach. Notice in this example, that we've added a custom validator on the ngModelGroup, that seems to break some basic validation premises - for example, notice that when the fields are invalid that the red highlighting only shows up next to the location field because the custom validator is on the ngModelGroup and onlineUrl is not inside that group.
Typing in the onlineUrl field does not automatically trigger the re-validation since this field is not in the ngModelGroup that has the custom validator on it. In order to make this work I needed to add this binding: (change)="locationGroup.control.controls.address.updateValueAndValidity()" to the onlineUrl field in order to trigger the validation on a field inside the ngModelGroup. This doesn't seem ideal.
Restating the Question: Is it possible to create some sort of validation context that spans multiple fields but does not modify the underlying model?
You can place 'validateLocation' directive up in the top 'form' tag:
<form #myForm="ngForm" (ngSubmit)="save(myForm)" autocomplete="off" novalidate validateLocation>
<fieldset ngModelGroup="location">
Then validate() method gets access to both location and onlineUrl via 'FormGroup.value' and will look like:
if (control && control.value && control.value.location) {
let g = control.value;
if (g.location.address && g.location.city && g.location.country)
return null;
if (g.onlineUrl)
return null;
}
return {validateLocation: false}
Try this plunker. Form.valid would become true when either location or url is captured.
I've seen heaps of questions about this, and all of them seem to be solved by either calling $scope.$apply(), $scope.$digest(), or by triggering the change() method on the input. But I can't seem to get it working with any of those methods. In this fiddle, I can type a name into the box and get the model value to update as I type. But when I click the link, to set the input name to a certain value, I want the model name to update. What do I need to do?
The reason I'm trying to do this is I want to be able to refresh my angular model when a user autofills the form, using the browser autofill or LastPass or similar. Surely there's some angular command to refresh the model from the DOM?
http://jsfiddle.net/PXCUq/
$(function () {
$('#setFirstName').click(function () {
$('input.firstname').val('Test Name');
angular.element($('input.firstname')[0]).scope().$apply();
// Model still not updated
});
});
Get the scope, then change the ng-model property:
$('#setFirstName').click(function() {
var scope = angular.element($('input').get(0)).scope()
scope.firstname = 'Test Name';
scope.$apply();
});
You can come up with a better jQuery selector. I was only focusing on the Angular part.
Fiddle.
I asked a pretty tough question on Jquery Validation earlier on, and nobody seems able to answer it, so I am just going to go for the more basic how-to question...
Say I have a form (MVC2 asp.net form might I add), one textbox, on textbox with DateTime in it and one radio button (the values of the Radio Button are Yes or No). How do I get simple custom validation on those Form Elements if I know the name of the form elements?
Keep in mind these elements are going to be generated Dynamically and so are there validation rules... I am for now just hoping to fudge it a little bit and put permanent validation in there...
I am a complete Jquery and Javascript nooob... All I have ever done with either programming language was add simple tools into my code...
Thank you for your help.
How do I get simple custom validation on those Form Elements if I know the name of the form elements?
The documentation contains many examples of how to setup the plugin. Here's an example with static rules:
$('#myform').validate({
rules: {
Name: {
required: true
},
DateOfBirth: {
required: true,
date: true
},
IsMajor: {
required: true
}
}
});
and if you wanted to dynamically add those rules you could do this:
$('#myform').validate();
and then dynamically add rules to individual form elements:
$('#Name').rules('add', {
required: true
});
$('#DateOfBirth').rules('add', {
required: true,
date: true
});
$('#IsMajor').rules('add', {
required: true
});
You don't need to know the id of the element as long as you assign it to the proper class, e.g. the built-in "required". Set the class and everything else is taken care of.
When you submit a form, disabled form fields are not submitted in the request.
So if your form has a disabled form field, it makes working with Zend_Form::isValid() a little frustrating.
$form->populate($originalData);
$form->my_text_field->disabled = 'disabled';
if (!$form->isValid($_POST)) {
//form is not valid
//since my_text_field is disabled, it doesn't get submitted in the request
//isValid() will clear the disabled field value, so now we have to re-populate the field
$form->my_text_field->value($originalData['my_text_field']);
$this->view->form = $form;
return;
}
// if the form is valid, and we call $form->getValues() to save the data, our disabled field value has been cleared!
Without having to re-populate the form, and create duplicate lines of code, what is the best way to approach this problem?
Are you setting the element to disabled so that the user can't edit it's contents but only to see it? If so, just set the element's readonly attribute to true, I think it'll work that way.
I use a custom class inherited from Zend_Form. Class adds some features and solves this problem by replacing the method isValid as follows:
class Murdej_Form extends Zend_Form {
function isValid($data) {
$_data = $this->getValues();
$valid = parent::isValid($data);
$this->populate($_data);
return $valid;
};
};
instead of using isValid() we can use isValidPartial(). Unlike isValid(), however, if a particular key is not present, it will not run validations for that particular element. So, isValidPartial() will not validate for disabled fields.
Reference: ZF Documentation