Angular 2 Cannot read property 'subscribe' of null for form field when using Validators.pattern - validation

I working on Angular 2 reactive forms. I facing an issue in form field validation using Validators.pattern(). As soon as I start typing in the input field will get the exception Cannot read property 'subscribe' of null.
TYPSCRIPT CODE
createForm(){
this.jobForm = this.fb.group({
name: ['', Validators.required, Validators.pattern(/^[a-zA-Z0-9]+$/)],
epType: ['ENDPOINT_TYPE_SBC', Validators.required],
streams : this.fb.array([
this.createStreamControls(),
]),
channels:this.fb.array([
this.createChannelControls(),
])
});
}
In 'name' attribute is validated against the pattern.
HTML CODE
<div class="ui-grid-col-8 ">
<input id="name" formControlName="name" pInputText class="width-60" />
<br>
<small *ngIf="jobForm.controls.name.hasError('required') && jobForm.controls.name.touched" class="text-danger">Required</small>
<small *ngIf="jobForm.controls.name.hasError('pattern') && jobForm.controls.name.touched" class="text-danger">Should be alpha-numeric without space</small>
</div>
Trying to validate input field name.
EXCEPTION Cannot read property 'subscribe' of null
Image showing Exception
When I remove the Validators.pattern() from name attribute it works fine. I am not able to understand why it is failing here because I have used Validators.pattern() in the same form for other attributes and it works fine for them.

Need to pass array of Validators in second argument of form group.
createForm(){
this.jobForm = this.fb.group({
name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9]+$/)]],
epType: ['ENDPOINT_TYPE_SBC', [Validators.required]],
streams : this.fb.array([
this.createStreamControls(),
]),
channels:this.fb.array([
this.createChannelControls(),
])
});
}

Related

Laravel: Textbox value is not getting received

View file:
<form action="" method="POST" enctype="multipart/form-data">
#csrf
<input type="checkbox" name="img_check" id="upload" value="dummy value">
<button type="submit" class="btn btn-primary">Update</button>
</form>
Controller file:
function editProduct(Request $request){
echo 'Checkbox value: '.$request->input('img_check');
............
............
............
return view('dashboard.editProduct', array('product' => $productData,
'categories' => $categoriesData,
'shippingPolicy' => $shippingPolicyData,
'returnPolicy' => $returnPolicyData,
'subcategory' => $subcategory,
'success' => $success));`
}
OUTPUT:
Checkbox value:
Output shows only text message, not textbox value.
All other fields of forms are working fine but only checkbox value is not getting received.
Surprisingly it is working fine on other form of mine which is being called from another controller. I tried a lot but couldn't figure out what is making textbox value fail!
Any idea?
EDIT:
Route path:
Route::match(['get', 'post'], 'edit_product', [dashboardController:: class, 'editProduct']);
your method should check whether request is post or get.So in request get method it return empty
public function editProduct(Request $request){
if($request->isMethod('POST')){
dd($request->input('img_check'));
}
return view('dashboard.editProduct', array('product' => $productData,
'categories' => $categoriesData,
'shippingPolicy' => $shippingPolicyData,
'returnPolicy' => $returnPolicyData,
'subcategory' => $subcategory,
'success' => $success));`
}
Update your route path to post as suggested by John.
If you are doing update operation it will be post method, get is only used for fetching the data.
Route::match(['post'], 'edit_product', [dashboardController:: class, 'editProduct']);
This is extremely strange behaviors of laravel 8.
What actually I did was, I copy checkbox field from other form of my project and paste it in current form (in which I was doing modifications). So simply copied one field from another form to my current form.
And laravel wasn't accepting this copy paste field as input field. It's value wasn't getting received and it wasn't entering in following if condition if($request->isMethod('POST')){ .
So finally I typed checkbox checkbox field by myself and that field started to work!!!!
I mean why..............!!?? If I copy paste any field from one page to another then laravel don't consider it as input field but if you typed then it started working!!
Here is my previous textbox field
<input type="checkbox" name="img_check" id="upload" value="dummy value">
And here it is my new checkbox field which I typed instead of copy paste
<input type="checkbox" name="allow" id="upload" value="hello">
And new checkbox was working. Damn I am so confused.... whats the difference between those fields?? IS this laravel's some kind of bug or what...?
NOTE: Both forms ware already being made and working. For little modifications I did copy one field from one to another form. On newly created form, copy paste field didn't bother me.

Unclear syntax in redux-form

Having trouble understanding the syntax in redux-form...
In redux-docs
const renderField = (field) => (
<div className="input-row">
<input {...field.input} type="text"/>
{field.meta.touched && field.meta.error &&
<span className="error">{field.meta.error}</span>}
</div> )
How is the spread operator used inside the input and why does the following returnes an error:
<input {...field.input, id} type="text"/>
The second syntax I dont understand is:
class MyCustomInput extends Component {
render() {
const { input: { value, onChange } } = this.props <---??
return (
<div>
<span>The current value is {value}.</span>
<button type="button" onClick={() => onChange(value + 1)}>Inc</button>
<button type="button" onClick={() => onChange(value - 1)}>Dec</button>
</div>
)
}
}
What is:
input: { value, onChange }
?
Queston 1:
The error from using {...field.input, id} should be something like the following:
Syntax error: ...: Unexpected token, expected }
If you already have props as an object, and you want to pass it in
JSX, you can use ... as a “spread” operator to pass the whole props
object (Spread Attributes)
So it appears the JSX attribute spread is not exactly the same as a es2015 spread. I believe it is limited to just the examples in the react docs.
Question 2:
The Field component passes these props to your wrapped component MyCustomInput
input.onChange(eventOrValue) : Function
A function to call when the form field is changed. It expects to either receive the React SyntheticEvent or the new value of the field.
input.value: any
The value of this form field. It will be a boolean for checkboxes, and a string for all other input types. If there is no value in the Redux state for this field, it will default to ''. This is to ensure that the input is controlled. If you require that the value be of another type (e.g. Date or Number), you must provide initialValues to your form with the desired type of this field.
In other words when MyCustomInput fires onChange the Field component will dispatch an action to update the form store.
The value prop is used to maintain the state MyCustomInput.

endDate > startDate in angular material

I am building a component (html, css, spec.ts, ts) in angular in which I always want endDate > startDate. I have followed this link https://material.angular.io/components/datepicker/overview in order make multiple datepickers.
This is the html which I have used for startDate and endDate.
startDate:
<div class="item item-1" fxFlex="50%" fxFlexOrder="1">
<mat-form-field>
<input matInput [matDatepicker]="picker1" placeholder="{{'PORTAL.STARTDATE' | translate}}" type="text" formControlName="startDate" [(ngModel)]="unavailability.startDate" [readonly]="!componentPermission.writePermission">
<mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
<mat-datepicker #picker1></mat-datepicker>
</mat-form-field>
</div>
endDate:
<div class="item item-2" fxFlex="50%" fxFlexOrder="2">
<mat-form-field>
<input matInput [matDatepicker]="picker2" placeholder="{{'PORTAL.ENDDATE' | translate}}" type="text" formControlName="endDate" [(ngModel)]="unavailability.endDate" [readonly]="!componentPermission.writePermission">
<mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-toggle>
<mat-datepicker #picker2></mat-datepicker>
</mat-form-field>
</div>
The validateForm() code which I have used in the ts is:
validateForm() {
this.unavailabilityForm = this.formBuilder.group({
'startDate': [''],
'endDate': ['']
});
}
I am pretty sure I have to make some changes in the validateForm() code but I am not sure what changes I have to make.
Since you seem to be going with a mix of reactive form and template driven, I would choose a reactive form completely. Implementing Validation is also in my opinion easier and cleaner. This also then means, you can drop ngModel altogether, which I would then strongly suggest, since it can cause unexpected issues to have two bindings (form control and ngModel). EDIT 2/2019: ngModel together with reactive forms are now also luckily not allowed since v7. That is in my opinion good, since it was misused way too much!
So build your form and attach a custom validator. In case you have a large form, I would attach the custom validator to a nested group of your dates, as it sits in this example, the validator is firing whenever there is any change in the form, doesn't matter if it's the date fields, or some other field.
constructor(private formBuilder: FormBuilder) {
this.unavailabilityForm = this.formBuilder.group({
startDate: [''],
endDate: ['']
}, {validator: this.checkDates});
}
If you are getting your values for variable unavailability at a later stage, you can use patchValue or setValue to assign the values to your form controls:
this.unavailabilityForm.setValue({
startDate: this.unavailability.startDate;
endDate: this.unavailability.endDate;
})
The custom validator simply checks that the end date is a later date than the startdate and returns null if it is valid, or then a custom validation error:
checkDates(group: FormGroup) {
if(group.controls.endDate.value < group.controls.startDate.value) {
return { notValid:true }
}
return null;
}
and then you can display this custom error in template with:
<small *ngIf="unavailabilityForm.hasError('notValid')">Not valid</small>
Also remember to mark this formgroup in your form tag:
<form [formGroup]="unavailabilityForm">

Redux Form - How to validate async blur field arrays?

I have a FieldArray like this:
renderLanguages = fields => (
<div>
{fields.map(fieldName => <Field name={fieldName + '.iso'} component="input" type="text" />
</div>
)
<FieldArray name="languages" component={renderLanguages} />
And i like to validate it in a async way:
const asyncValidate = values => {
console.log(values);
}
export default reduxForm({
form: 'languagesForm',
asyncValidate,
asyncBlurFields: ['languages']
})(LanguagesForm)
My asyncValidate never gets called. I wonder if i have to specify the asyncBlur fields in an other way. Or if redux-form does not provide the async validation of field arrays.
To get Redux-form FormArray working with the asyncValidate, it requires to pass the field as languages[].<nameOfTheFieldOfChildComponet> but not languages only.
I think its good design too as generally, we don't validate asynchronously on change of any parameter but a specific parameter.
Here is the working example:- https://codesandbox.io/s/mq8zz58mrj
const asyncValidate = values => {
console.log(values);
}
export default reduxForm({
form: 'languagesForm',
asyncValidate,
asyncBlurFields: ['languages[].name']
})(LanguagesForm)

Validation in knockout js input fields

I created some input fields using KnockoutJS, and now I want to validate them.
http://jsfiddle.net/sohimohit/43zkoszu/12/
I tried it using validation plugin but it doesn't work.
I added that plugin and used it as mentioned but didn't get the solution. When you click on "add field" a form appears; I want to make the name field required and branch id as numeric. However, when I click on "add fields" it doesn't get added until the form is validated.
How can I achieve this?
You are not doing validation properly. I recommend this method
Set some settings
ko.validation.configure({
insertMessages: false,
decorateElement: true,
errorElementClass: 'error-element',
errorClass: 'error-element',
errorsAsTitle: true,
parseInputAttributes: false,
messagesOnModified: true,
decorateElementOnModified: true,
decorateInputElement: true
});
Make inputs bind with validationElement
<input type="text" placeholder="Name" data-bind="value:name,validationElement:name">
<input type="text" placeholder="Branch" data-bind="value:branch,validationElement:branch">
Extend observables
self.name = ko.observable().extend({required:true})
self.branch = ko.observable().extend({required:true,digit: true})
Now apply the rule. I prefer group
var data = [
self.name,
self.branch
]
self.Errors = ko.validation.group(data);
Now on add button wrap your code
self.Add = function(){
if(self.Errors.length == 0){
.
.
.
//Your code here
}else{
self.Errors.showAllMessages()
}
}
Hope it helps

Resources