I have an Angular Reactive form. I subscribe to its value changes and will emit changes to parent component. Some of the controls might get disabled by the user. The problem is that values from disabled controls are missing when form valueChanges are emitted. I've set a basic example.
When the checkbox is checked and the email input is disabled, there is no form control value logged. But I'd like to get ALL form values.
Use the FormGroup's getRawValue() to include control values regardless of enable/disable state.
More information in the API documentation
this.myForm.valueChanges.subscribe(() => {
this.formValues = JSON.stringify(this.myForm.getRawValue());
});
Here is the forked example
The value from a disable input is ignored (try to submit a form with a disabled input: it won't be posted).
You can change it to 'readonly'
<input formControlName="email" [readonly]="cb.checked">
<input #cb type="checkbox" formControlName="toggleEmail">
Updated example.
this.form.valueChanges
.pipe(map((_) => this.form.getRawValue()))
.subscribe(res => {
console.log(res)
});
Related
I am struggling to figure out a way to trigger these AngularJS classes on a form I am trying to automatically fill with a chrome extension I am making. The form (specifically a textbox) has to be validated/modified before it will be validated and therefore submitted.
I originally tried using javascript to set the value of the textbox using the value property. This did not validate the form. I then tried using a dispatch event to send a key to the textbox, which resulted in nothing being input into the text box. How can I validate the form without requiring human input, or is this not possible?
Clarification, I am trying to replicate this action without user input by using a chrome extension.
Reference https://www.w3schools.com/angular/angular_validation.asp
Sounds like you need to create some events to simulate whatever angular is listening for, probably change or blur. Here's an example using click from mozilla:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#Triggering_built-in_events
function simulateClick() {
var event = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
var cb = document.getElementById('checkbox');
var cancelled = !cb.dispatchEvent(event);
if (cancelled) {
// A handler called preventDefault.
alert("cancelled");
} else {
// None of the handlers called preventDefault.
alert("not cancelled");
}
}
How can I validate the form without requiring human input
Get the forms controls:
var controls = $scope.tdForm.$getControls();
Trigger their validators:
controls.forEach( _ => _.$validate() );
From the Docs:
$validate();
Runs each of the registered validators (first synchronous validators and then asynchronous validators). If the validity changes to invalid, the model will be set to undefined, unless ngModelOptions.allowInvalid is true. If the validity changes to valid, it will set the model to the last available valid $modelValue, i.e. either the last parsed value or the last value set from the scope.
For more information, see
AngularJS Form Controller API Reference
AngularJS ngModelController API Reference
When you type into the form, it updates the state of its controls (touched, dirty, etc.). According to how you define your fields validators (required, minLength...) the form will be valid or not after the user input.
In your submit method you should not proceed if any form fields are not valid. See AngularJS Developer Guide — Forms or Scotch Tutorials — AngularJS Form Validation you can have more details about AngularJS validation.
As Mike mentioned, you can use ngClass conditionally (see below) to apply some style classes only if a boolean condition occurr, for example the form is not valid.
<div ng-controller="ExampleController">
<form name="form" novalidate class="css-form">
<input type="text" ng-model="user.name" name="username" ng-class="{ 'error': !isValid }"/>
<div ng-show="form.$submitted>
<span ng-show="form.username.$error">Wrong Name</span></span>
</div>
<button ng-click="submit(user)"> Submit </button>
</form>
</div>
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.isValid = true;
$scope.submit= function(user) {
if (user.name != 'Carl') {
$scope.isValid = false;
}
};
}]);
You can always programmatically change the form states if needed. For example to set the field to pristine:
$scope.form.$setPristine();
$scope.form.$setUntouched();
$setPristine sets the form's $pristine state to true, the $dirty state to false, removes the ng-dirty class and adds the ng-pristine class.
Additionally, it sets the $submitted state to false. This method will also propagate to all the controls contained in this form.
$setUntouched sets the form to its untouched state. This method can be called to remove the 'ng-touched' class and set the form controls to their untouched state (ng-untouched class).
Setting a form controls back to their untouched state is often useful when setting the form back to its pristine state.
UPDATE
Now it is clear what you are attempting to achieve. The two methods above can be used to set the form state, but if you want to validate it from code (this can be done passing the form to a service or directly in the controller for instance) then $validate() method will allow you to achieve that as mentioned by George.
I want to put some text in to the radio field (with Redux form).
I have fields like this:
<Field
name={some.name1}
value={'text1'}
component={renderRadioElement}
type="radio"
/>
<Field
name={some.name2}
value={'text2'}
component={renderRadioElement}
type="radio"
/>
...
Everything works correctly until the first value change.
If I want to change the value several times: state -> form -> ... -> values -> some does not update values.
My question is - how to correctly enter a text value into a radio field?
If I understood correctly your comment you have a value on your component state where youve decleared the form and you wnat to pass in that value to your field.
If thats it what you want to do is dispatch the value to the redux-form store.
To do that in your class you are receiving a prop which is change. injected by redux-form. what you want to do is use that function to set the value
const { change } = this.props;
change('some.name2', this.state.yourValue)
hope it helps
When upgrading to Angular 4, I am getting the following warning in the console:
it looks like you're using the disabled attribute with a reactive form
directive. If you set disabled to true when you set up this control in
your component class, the disabled attribute will actually be set in
the DOM for you. We recommend using this approach to avoid 'changed
after checked' errors.ֿ
When doing something like this:
<input type="text" formControlName="name" [disabled]="isDisabled">
it's seems that Angular does not like anymore when we use the disabled property on form control.
What is changed and why it's happening?
It means that you are setting the disabled property through property binding, but you are using formControl which gives reactive nature.
So, you should be declaring the {disable: true} in the code as below,
form = new FormGroup({
name: new FormControl({value: '', disabled: true})
});
Note: If you are using reactive forms you should be having a formGroup attribute defined in your HTML.
LIVE DEMO
I have an input file element within an angular view/form. I'm using ng-upload like this:
<input id="img" type="file" name="image" onchange="angular.element(this).scope().setFile(this)">
<input id="imgname" type="hidden" value=""></div>
Since I can't tell angular to listen for changes on input[type="file"] element, I've created the method that updates the hidden input that just holds the current filename. That way I can run my validator on the second field.
Another field I have has some sort of validator, like this:
<input ng-model="other" ng-change="chg()"/>
Now, the trouble is, if I trigger the validator, $scope.chg(), from setFile() method, I think I don't get the same scope - chg() runs, but it's as if the validator is in another scope and doesn't set my actual submit button to enabled. I tried logging from the chg() - it shows different scope then what I actually see on the view.
And if I later trigger the ng-change by changing the regular input field ("other"), it picks up the changes, or actually, it sets the submit button state correctly.
Now, I suspect this has to do with me calling the angular.element(this).scope().setFile(this) from my form instead of direct, $scope-bound method. But I cannot call $scope-bound method because it does not trigger - if I understood correctly, that's due to Angular not (yet) working with input type=file fields.
What can I do here?
I simply want to detect if there is a file or not so I can enable/disable the submit button appropriately.
I used followed flow that works for me:
<input type="file"
ng-model="upFile"
onchange="angular.element(this).scope().setFileEventListener(this)"
/>
From controller:
$scope.setFileEventListener = function(element) {
$scope.uploadedFile = element.files[0];
if ($scope.uploadedFile) {
$scope.$apply(function() {
$scope.upload_button_state = true;
});
}
}
Hope it will help.
I have a MVC3 app using Project Awesome (http://awesome.codeplex.com/), but I am getting a weird behaviour on checkboxes. I have the following simple Html within a Modal popup <input type="checkbox" class="check-box" name="IsDeleted">
When I submit the form containing this element, its post value is 'on' instead of the expected 'true' (when element is checked).
Does anybody know why this is? I am assuming there may be some javascript somewhere messing with the form data, but wanted to check whether there isn't some HTML I am missing.
Thanks
Set the checkboxes value attribute to true and you will get true in your post value.
It's browser specific, I suppose, what to send when value is undefined. You need to defined value attribute on your radios/checkboxes to be sure what will be passed back to you. I would suggest value="1"
set data-val="true" and value="true" by deafult...
if checkbox is checked then returns true
Check Checkbox is checked or not if checked set Hidden field true else set hidden field false.
$('#hiddenFieldId').val($('#CheckBoxId').attr('checked')=='checked')
Surely you should just check if it is set - the value that it sends across is irrelevant, if it's not checked, then nothing at all gets sent when you POST.
Nothing worked!
I ended up on a hacky way after seeing the serialised form object just before posting to controller/action. Its not safe in case if anyone would have any textboxes inside that may contain ampersands. In my case, i had an array of checkboxes, so I did this hack after I am very sure, i won't have problems.
var formData = $("#form").serialize();
formData = formData.replaceAll('=on&','=true&');
if (formData.endsWith('=on'))
{
formData = formData.substring(0, formData.length - 3) + "=true";
}
Hope it helps to those 'someone' with my scenario. Happy hacking.
Use jQuery for cross-browser decision. And it will return true or false anyway.
$('#check-box-id').attr('checked' ) == true
if your checkbox has an id check-box-id. For your current version use the next (select by class name):
$('.check-box').attr('checked' ) == true
Use jQuery
var out=$('.check-box').is('checked')
If checkbox is checked out=true
else out=false
In HTML, add a input type="hidden" above checkbox:
<input name="active" id="activeVal" type="hidden">
<input id="active" type="checkbox">
Then, add a script as below:
$('#activeVal').val($('#active').is(':checked'));
$('#active').change(function() {
$('#activeVal').val($('#active').is(':checked'));
});
When you do eg. $('#your-form').serialize() in jQuery, you will get value of checkbox when checked active: true or uncheck active: false