How to separate 'Implemented Conditional Validation Service/Function' in Angular-8 while using Reactive-Forms - angular-reactive-forms

I have implemented conditional Validation in my Component.
I am trying to separate the validation logic from my component to another component/service.
Demo Link : http://StackBlitz%20https://stackblitz.com/edit/angular-amr86r

You can easily apply conditional validation using #rxweb/reactive-form-validators. I have applied required validation through both validator as well as decorator based approach. Please refer to the working example.
Using Decorator based approach:
You just need to apply #required() decorator with the condition you want to apply on your model-property.
Here is the complete model code:
import { required } from "#rxweb/reactive-form-validators"
export class UserInfo {
#required()
firstName: string;
#required({conditionalExpression:'x => x.firstName == "Bharat"' })
lastName: string;
}
Using Validator based approach:
For validator based approach, you just need to mention RxwebValidators.required() with the condition you want to apply on your form-control.
Here is the complete component code:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder } from "#angular/forms"
import { RxwebValidators } from '#rxweb/reactive-form-validators';
#Component({
selector: 'app-validator-based-validator',
templateUrl: './validator-based.component.html'
})
export class ValidatorBasedValidationComponent implements OnInit {
validatorBasedFormGroup: FormGroup
constructor(
private formBuilder: FormBuilder )
{ }
ngOnInit() {
this.validatorBasedFormGroup = this.formBuilder.group({
firstName:['', RxwebValidators.required()],
lastName:['', RxwebValidators.required({conditionalExpression:'x => x.firstName == "Bharat"' })]
});
}
}
Note : if you will use validator approach then, You can create a function in a separate file and use that respective function in the condtional expression property. In anyway, the model file will be separated in decorator based approach.

Related

Avoid circular dependency when using interface in Nestjs/GraphQL

I was following the code first approach to defining a GraphQL interface in the Nestjs docs.
However, the resolveType() requires that you return a class instance and forces me to import the classes that implements the interface (I have the classes in different files); this creates circular depedencies amongst my classes and the interface files.
Example:
book.interface.ts:
import { ColoringBook } from './coloring-book.model.ts
import { TextBook } from './textbook.model.ts
#InterfaceType(resolveType(book) {
if (book.colors) {
return ColoringBook;
}
return Textbook;
})
abstract class Book {
// class members...
}
coloring-book.model.ts:
import { Book } from './book.interface.ts';
#ObjectType({ implements: Book})
class ColoringBook implements Book {
// class members...
}
textbook.model.ts:
import { Book } from './book.interface.ts';
#ObjectType({ implements: Book})
class Textbook implements Book {
// class members...
}
I've tried this like:
resolveType(book) {
if (book.colors) {
return forwardRef(() => ColoringBook);
}
return forwardRef(() => TextBook);
}
but that doesn't help as I still need to import the class and it doesn't actually resolve at runtime.
What would be a best practice way of avoiding this circular dependency short of consolidating everything to one file?
I ended up following how it was done here:
#InterfaceType({
resolveType: value => value.constructor.name,
})
I am not sure if this has any side effects underlying but it definitely looks cleaner and doesn't require me to circular import.
Building on your answer:
It seems like you can simply pass the class name instead of the JS class, which results in:
book.interface.js
// no import
#InterfaceType(resolveType(book) {
if (book.colors) {
return 'ColoringBook';
}
return 'Textbook';
})
abstract class Book {
// class members...
}
In my case, value.constructor.name was systematically the Interface name (Book instead of <Specifier>Book)

converting class component to useState

This is a class component that is using state and setState, but i would like to use useState. Also, aside from being able to use a functional component rather than a class base component, what are the benefits?
import React, {Component} from "react"
class Toggler extends Component {
state = {
on: this.props.defaultOnValue
}
toggle = () => {
this.setState(prevState => {
return {
on: !prevState.on
}
})
}
static
defaultProps = {
defaultOnValue: false
}
render() {
return (
<div>
{this.props.render(this.state.on, this.toggle)}
</div>
)
}
}
export default Toggler
So far...
import React, {useState} from "react"
function Toggler() {
const [on, setOn] = useState(this.props.defaultOnValue)
toggle = () => {
setOn( {/* what should go here? */} )
}
static
defaultProps = {
defaultOnValue: false
}
return (
<div>
{this.props.render(on, toggle)}
</div>
)
}
export default Toggler
Toggling your state value is as simple as inverting the current value returned from useState.
Functional components receive the props passed to them as an argument, so no need to use this.props. Also, to set static properties on a functional component you can just set them on the function itself.
function Toggler(props) {
const [on, setOn] = useState(props.defaultOnValue)
const toggle = () => {
setOn(!on)
}
return <div>{props.render(on, toggle)}</div>
}
Toggler.defaultProps = {
defaultOnValue: false
}
export default Toggler
In terms of benefits, it's up to you to decide whether you think it's worth it for your case. There's no specific benefit to using useState rather than a class based component, however if you want to start using other hooks, or integrate with third party libraries using hooks, you may wish to convert some of your components to functional ones where necessary.

How to import js file(s) inside vue component (laravel) [duplicate]

I want to use a javascript class in may Vue application.
My class looks like:
class className {
constructor() {
...
}
function1() {
...
}
static funtion2() {
...
}
}
I tried to import this class in my application like:
import className from './fileName.js';
var {className} = require('./fileName.js')
In all cases I receive when I want to call a function of the class (className.function2()): the function is undefined.
You need to export the class to be able to import/require it
//1. For import syntax
export default class className {...}
//2. For require syntax
class className {}
module.exports.className = className
//or
module.exports = {
className: className
}
Using import/export, you'd use
export class className {}
and
import {className} from '<file>';

How to handle redux-form/CHANGE in reducer

What is the recommended way to handle redux-form/CHANGE actions being dispatched by redux-form? I have my own reducer managing the state of this form but I'm not sure if it's best to do the following:
export default reducer (state = initialState, action) {
case 'redux-form/CHANGE':
// return modified state
}
One problem I see is that this reducer would receive every redux-form/CHANGE action. Additionally as far as I can tell ActionTypes.js isn't exported in a way for me to import it so I feel as though this may not be best practice.
You can definitely use redux-form action creators. You just have to connect it to your component.
So in your /components/MyComponent.js
import React from 'react';
import { connect } from 'react-redux';
import { change } from 'redux-form';
class MyComponent extends React.Component {
...
render() {
return <div>
<button onClick={this.props.change('formName', 'fieldName', 'value')}>Change</button>
</div>
}
}
const mapStateToProps = (state, ownProps) => { ... }
export default connect(mapStateToProps, { change })(MyComponent);
You could also use redux-form reducer and extends it to your needs...
In your reducers/index.js]
import { reducer as form } from 'redux-form';
const formPlugin = {
formName: (state, action) => {
...reducer logic
return newState;
}
}
const rootReducer = combineReducers({
...other reducers,
form: form.plugin(formPlugin)
});

How to change validation of a control after it has been initiated?

I am wondering how can I dynamically change Validation on a field. I have control group, which has 5 fields. For this, I want to use custom validator on this control group, to check if any of the inputs are not empty. If any of those are empty, I want to set validation of all of the fields within this control group to be required.
To do this, I need to dynamically change validation of each control to be required, after I verify if any of the inputs are empty. I got the first part - but I still cant figure out how to change validation of a control after it has been initiated. Any ideas?
What I am doing at the moment, is I put a validator on the group like this:
this._formBuilder.group({....}, {validator: customValidator})
You can use a custom validator that changes behavior depending on a value
class MyComponent {
constructor(fb:FormBuilder) {
this.form = fb.group({
c1: ['', (c) => this.myValidator(c)],
...
});
}
someState = true;
myValidator(c:Control) {
if(this.someState && control.value ....) {
}
}
}
This way the validator can for example access the status of the current component. You can also move the validator to another class and pass the method reference of that class to the validator parameter and update properties of this class to change the behavior of the validator.
class MyValidator {
someState = true;
validate(c:Control) {
if(this.someState && control.value ....) {
}
}
}
class MyComponent {
myValidator = new MyValidator();
constructor(fb:FormBuilder) {
this.form = fb.group({
c1: ['', this.myValidator.validate.bind(this.myValidator)],
...
});
}
onSomeEvent() {
this.myValidator.someState = !this.myValidator.someState;
this.form.control.c1.updateValueAndValidity();
}
}

Resources