angular 2 pass array to custom validator (Template driven form) - validation

I need to pass an array of objects to the a2 custom validator and then I d like to validate the value of the template driven form field against the records in that array.
However I can not retrieve the object inside the validator.
The only thing I can see is its name as string.
Any help is kindly appreciated.
<label class="btn btn-default btn-sm"
[(ngModel)]="krediHesaplamaModel.radioModelKrediTur" name="krediHesaplamaModel.radioModelKrediTur"
btnRadio="0"
(click)="onRadioButtonKrediHesaplamaTurChange()" krediTuruValidator="this.krediList" >
import { Directive, forwardRef, Attribute } from '#angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '#angular/forms';
import {Kredi} from '../kredi';
#Directive({
selector: '[krediTuruValidator][formControlName],[krediTuruValidator][formControl],[krediTuruValidator][ngModel]',
providers: [{ provide: NG_VALIDATORS, useExisting: forwardRef(() => KrediTuruValidator), multi: true },
]
})
export class KrediTuruValidator implements Validator {
constructor( public krediTuruValidator: Kredi[]) { }
validate(c: AbstractControl): { [key: string]: any } {
console.log('KL' + this.krediTuruValidator[0].krediTuru); //UNDEFINED
let v = c.value;
return null;
}
}

I resolved this issue by delegating the validation function to another method in the component. That way I can access any object I desire
import { Directive, forwardRef, Attribute, Input } from '#angular/core';
import { Validator, ValidatorFn, AbstractControl, NG_VALIDATORS } from '#angular/forms';
#Directive({
selector: '[krediVadeSayisiValidator][formControlName],[krediVadeSayisiValidator][formControl],[krediVadeSayisiValidator][ngModel]',
providers: [{ provide: NG_VALIDATORS, useExisting: forwardRef(() => KrediVadeSayisiValidator), multi: true },]
})
export class KrediVadeSayisiValidator implements Validator {
#Input() krediVadeSayisiValidator: ValidatorFn; //same name as the selector
validate(c: AbstractControl): { [key: string]: any } {
return this.krediVadeSayisiValidator(c);
}
}
How do I access it inside the template?
<input type="number" class="form-control" name="krediVadeSayisi" [(ngModel)]="krediHesaplamaModel.krediVadeSayisi" #krediVadeSayisi="ngModel"
required maxlength="2" [krediVadeSayisiValidator]="validateKrediVadeSayisi()" /> /*this function is inside the component*/

Related

How to retrieve dropdown items from an observable?

How would you retrieve dropdown items from an observable in #rxweb/reactive-dynamic-forms ?
how do you inject service in FormControlConfig subclass? shared code here https://stackblitz.com/edit/angular-bs5yqt-nmzcwj
For injecting custom services into the dynamic form control source model you have to pass the respective service into the argument of model configuration.
Step 1
Create a Service according to your need, I am creating fake ConfigService.
import { HttpClient} from "#angular/common/http"
import { Injectable } from "#angular/core"
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
configUrl = 'assets/config.json';
getConfig() {
return this.http.get(this.configUrl);
}
}
Step 2
Let's create a Model, which is extended with FormControlConfig for async source binding.
import { FormControlConfig } from "#rxweb/reactive-dynamic-forms"
import { ConfigService } from "./config.service"
export class SourceAsyncConditionalModel extends FormControlConfig{
constructor(fieldConfig: { [key: string]: any }, public controlsConfig: { [key: string]: FormControlConfig },notificationId:number,private configService:ConfigService){
super(fieldConfig,controlsConfig,notificationId);
}
filter() {
let promise = new Promise<any>((resolve, reject) => {
/// call the service
if(this.configService)
this.configService.getConfig();
});
}
}
If you see the above the code where I have defined four parameters. The first three parameters are used in FormControlControl and the fourth parameter we can use in the model instance.
Step 3
Now, we have to pass the parameter with respective model. See the below code :
this.dynamicFormConfiguration = {
controlConfigModels: [{ modelName: 'sourceAsync', model: SourceAsyncConditionalModel,arguments:[this.configService] }],
}
this.dynamicFormBuildConfig = this.formBuilder.formGroup(this.serverData, this.dynamicFormConfiguration);
Here is the working Example

load data to grid in angular 6 using http get

Im trying to load the following sample data to jqgrid(free) using http.get in angular 6.
[{"maker":"Toyota", "model":"Celica"},{ "maker": "Chrysler", "model":"Mondeo"}]
Model Class
export class Model{
maker : string
model : string
}
Component:
...
#Component({...})
export class SampleComponent implements OnInit {
private _sampleService;
columnModel : any[];
models : Model[];
constructor(_sampleService : SampleService) {
this._sampleService = _sampleService;
}
ngOnInit() {
this.columnModel = [{ name: "maker" },{ name: "model" }]
this.models = this._sampleService.getModelList().subscribe(models => this.models = models);
}
ngAfterViewInit() {
(<any>jQuery("#grid")).jqGrid({
colModel: this.columnModel,
data: this.models
});
}
}
Service:
....
#Injectable()
export class SampleService{
constructor(private http : HttpClient){}
getModelList():Observable<Model[]>{
return this.http.get<Model[]>
("http://localhost:8090/myapp/getModel");
}
}
If I do the following, I can see the data in the console.
this.http.get("http://localhost:8090/ducksoup/getModel")
.subscribe(data => {console.log(data)})
But,it is not rendering in the grid. Any help?
You can write your jqxGrid binding code inside of OnInit method, right after you fetch your records and it will show your data on datagrid

How do I dynamically set validations fields in vuelidate

I'm using VueJS2 with vuelidate library. I can validate the fields based on the validation objects. The validation will execute during computed time. But My validations objects is fixed, instead of dynamic. I have some fields will hide based on the selection.
import { validationMixin } from 'vuelidate'
import { required, maxLength, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
company_name: { required },
company_position_title: { required }
},
methods: {
submit(){
this.$v.touch();
if(this.$v.$invalid == false){
// All validation fields success
}
}
}
}
HTML
<v-select
label="Who are you?"
v-model="select" // can be 'company' or 'others'
:items="items"
:error-messages="selectErrors"
#change="$v.select.$touch();resetInfoFields();"
#blur="$v.select.$touch()"
required
></v-select>
<v-text-field
label="Company Name"
v-model="company_name"
:error-messages="companyNameErrors"
:counter="150"
#input="$v.companyName.$touch()"
#blur="$v.companyName.$touch()"
v-show="select == 'Company'"
></v-text-field>
<v-text-field
label="Company Position Title"
v-model="company_position_title"
:error-messages="companyPositionErrors"
:counter="150"
#input="$v.companyPosition.$touch()"
#blur="$v.companyPosition.$touch()"
v-show="select == 'Company'"
></v-text-field>
<v-btn #click="submit">submit</v-btn>
Problem
When I select 'other' option and click submit, the this.$v.$invalid is still true. It should be false as there is no validation fields required.
When I select 'company', that two fields must required and validated.
you need a dynamic validation schema
validations () {
if (!this.select === 'company') {
return {
company_name: { required },
company_position_title: { required }
}
}
}
More info: Dynamic validation schema
Another way is using requiredIf
itemtocheck: {
requiredIf: requiredIf(function () {
return this.myitem !== 'somevalue'
}),
minLength: minLength(2) },

Autoform with Meteor React and Simple-Schema

Is there any possibility to make meteor-autoform work with meteor-collection2-core and react-meteor?
MWE
Preferably I would like to have something like this.
./imports/api/Books.js
import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema';
const Books = new Mongo.Collection("books");
Books.attachSchema(new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200
},
author: {
type: String,
label: "Author"
},
}));
if (Meteor.isServer) {
Meteor.publish('allBooks', function () {
return Books.find({}, );
});
};
export default Books;
./imports/client/NewBooks.js
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { quickForm } from 'meteor-autoform';
import Books from '../api/Books';
class NewBooks extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
<div className="container">
<quickForm
collection={Books}
id="insertBookForm"
type="insert">
</quickForm>
</div>
)
}
};
export default createContainer(() => {
Meteor.subscribe('allBooks');
return {
books: Books.find().fetch()
}
}, NewBooks);
The npm package Uniforms worked super easy with Bootstrap.
Addition to ./imports/client/NewBooks.js
import AutoForm from 'uniforms-unstyled/AutoForm';
...
<AutoForm
schema={Books._collection.simpleSchema()}
onSubmit={doc => console.log(doc)}
/>
To my knowledge, Autoform depends heavily on Blaze, so, you could either use blaze autoform components in react (see here), or you can use a different library for this. I used this in a recent project: github.com/nicolaslopezj/simple-react-form. It's powerful, but much more 'hands-on' than the magical Autoform (you have to write your own form and field components).

Conditional required validator directive in Angular 2

I need to make certain form fields required or not based on the value of other fields. The built-in RequiredValidator directive doesn't seem to support this, so I created my own directive:
#Directive({
selector: '[myRequired][ngControl]',
providers: [new Provider(NG_VALIDATORS, { useExisting: forwardRef(() => MyRequiredValidator), multi: true })]
})
class MyRequiredValidator {
#Input('myRequired') required: boolean;
validate(control: AbstractControl): { [key: string]: any } {
return this.required && !control.value
? { myRequired: true }
: null;
}
}
Sample usage:
<form>
<p><label><input type="checkbox" [(ngModel)]="isNameRequired"> Is Name Required?</label></p>
<p><label>Name: <input type="text" [myRequired]="isNameRequired" #nameControl="ngForm" ngControl="name" [(ngModel)]="name"></label></p>
<p *ngIf="nameControl.control?.hasError('myRequired')">This field is required.</p>
</form>
This works fine if the user first toggles the check box and then types or erases text in the text box. However, if the user toggles the check box while the text box is blank, then the validation message doesn't update appropriately.
How can I modify MyRequiredValidator to trigger validation when its required property is changed?
Note: I'm looking for a solution that only involves changes to MyRequiredValidator. I want to avoid adding any logic to the App component.
Plunker: https://plnkr.co/edit/ExBdzh6nVHrcm51rQ5Fi?p=preview
I would use something like that:
#Directive({
selector: '[myRequired][ngControl]',
providers: [new Provider(NG_VALIDATORS, { useExisting: forwardRef(() => MyRequiredValidator), multi: true })]
})
class MyRequiredValidator {
#Input('myRequired') required: boolean;
ngOnChanges() {
// Called when required is updated
if (this.control) {
this.control.updateValueAndValidity();
}
}
validate(control: AbstractControl): { [key: string]: any } {
this.control = control;
return this.required && !control.value
? { myRequired: true }
: null;
}
}
See this plunkr: https://plnkr.co/edit/14jDdUj1rdzAaLEBaB9G?p=preview.

Resources