fromEvent not fire when I put HTMLElement, and fire when I put Jquery Object - rxjs

Code Here
If I put $('input') as parameter of fromEvent it will fire when I call $('input').trigger('input'). But if I put document.getElementsByTagName('input') as parameter it will not fire. It will fire only when I type, but not fire when I call $('input').trigger('input').
Can someone explain why?
Note: $('input').on('input', _ => console.log) will work in both cases.

it's because the ngOnInit hook is running before the view is built, so the document selector is querying before the element is there, but jquery selectors are actually async waiting for the document to be ready.
here's how you do it the angular way:
#ViewChild('inp')
input
// use the after view init hook
ngAfterViewInit() {
fromEvent(this.input.nativeElement, 'input') // angular way
.pipe(
tap(_ => {
console.log("tap input");
})
)
.subscribe(_ => {
console.log("subscribe input");
});
}
in your html, add this:
<input type="text" #inp>
or the even better angular way (not using fromEvent)...
<input type="text" (input)="showMe($event)">
then in component just have this:
showMe(e) {
console.log(e)
}
https://stackblitz.com/edit/angular-ivy-jfoc7d?file=src%2Fapp%2Fapp.component.html

Related

How to call parent function in jquery apline js

I'm facing one issue when clicking on the button this.reloadDatatable() is not called. how can I call reloadDatatable() function from toggle function? below is the demo code for that. Thank you.
<button type="button" #click="addSettingContainer.toggle();"></button>
Alpine.data('initOrderGrid', () => ({
addSettingContainer: {
toggle() {
this.reloadDatatable();
}
},
reloadDatatable: function() {
console.log('a');
},
}));
You cannot access the parent object's scope from a child object without some ugly hacks. However it seem that you want to use an event system: on a button click you want to reload the data table. Alpine.js has builtin event system, we can use the $dispatch function to emit a custom event and the x-on method to capture our custom event:
<div x-data="initOrderGrid"
#reload-data-table.window="reloadDatatable">
</div>
<div x-data>
<button #click="$dispatch('reload-data-table')">Reload data table</button>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('initOrderGrid', () => ({
reloadDatatable() {
console.log('Data table reloaded');
}
}))
})
</script>

Reading form inputs?

How would you read the input value ?
On the reacjs site I see very complicated way !!
https://reactjs.org/docs/forms.html
I just want to read the value and submit it via ajax fetch() request. I.e. I don't need to manage bindings, events and such ...
The easiest way by far to read values from html controls is by using an event handler.
export default class myComponent extends Component {
person = {};
onChange = field => e => {
this.person[field] = e.target.value;
};
render() {
return (
<Input
id="firstName"
name="firstName"
autoComplete="firstName"
autoFocus
onChange={this.onChange('FirstName')}
/>
);
}
}
In the above code snippet we are basically telling react to fire the onChange member on an update of firstName control update. Our method will receive an event e, that has a handle to our control and we can basically probe it's value member to get what's typed in (much like jquery's $('#element').value()).
Why is it the easiest method? because it's generic enough to allow you to handle multiple inputs in a react component. Notice that, I'm also instructing React to pass me the control name in addition to the event, and using this method I can basically know exactly which of my inputs (in case of multiple) caused the event to fire.
Reading user input value is feasible and recommended via event handlers.
Below example would explain how to read input value and send it to the backend via fetch when Form is submitted
class Test extends Component{
constructor(props){
super(props);
this.state = {
name: “”
}
}
handleChange = event => {
this.setState({name: event.target.value});
}
handleSubmit = () => {
//send the value via fetch backend I.e., this.state.name
}
render(){
const { name } = this.state;
render(
<form onSubmit={this.handleSubmit}
<label>
Name:
<input type="text" value={name} onChange={this.handleChange} name="name" />
</label>
<input type="submit" value="Submit" />
</form>
)
}
}

Angular 5 - Reactive forms doesn't validate form on submit

I have a simple form as below:
some.component.html
<form class="example-form" novalidate (ngSubmit)="onSubmit()" autocomplete="off" [formGroup]="testform">
<input type="text" formControlName="name" class="form-control" placeholder="Enter name" required/>
<app-show-errors [control]="claimform.controls.name"></app-show-errors>
<button type="submit" (click)="onSubmit()">Next</button>
</form>
some.component.ts
ngOnInit() {
this.testform= new FormGroup({
name: new FormControl('', { validators: Validators.required})
}, {updateOn: 'submit'});
}
onSubmit() {
if (this.testform.valid) {
alert('saving data');
} else {
this._validationService.validateAllFormFields(this.testform);
}
}
validationService.ts
validateAllFormFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
}
});
}
Reference
Problem
The form will validate on submit if left blank, but even after filling the value when I check this.testform.valid it returns false. But if I remove updateOn:'submit' on form then it validates on blur of input control and when value is entered it validates form return true. Not sure if updateOn is working fine or not or whether I've implemented this in a proper way. Could someone point me in the right direction.
in your HTML you have two calls to onSubmit() function, from submit button:
<button type="submit" (click)="onSubmit()">Next</button>
and from the form:
<form class="example-form"
ovalidate
(ngSubmit)="onSubmit()"
autocomplete="off"
[formGroup]="testform">
The first call to be triggered is the button's trigger, which actually does nothing in terms of updating your reactive form, since you set FormGroup's option to {updateOn: 'submit'}. The second call to be triggered is the form's trigger, which does actual form update.
Here is FormGroup directive config:
#Directive({
selector: '[formGroup]',
providers: [formDirectiveProvider],
host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
exportAs: 'ngForm'
})
as we can see in host property DOM form's submit (triggered by hitting ENTER while focused within form or clicking form's submit button) will call onSubmit() function:
onSubmit($event: Event): boolean {
(this as{submitted: boolean}).submitted = true;
syncPendingControls(this.form, this.directives);
this.ngSubmit.emit($event);
return false;
}
which then will call syncPendingControls() function:
export function syncPendingControls(form: FormGroup, directives: NgControl[]): void {
form._syncPendingControls();
directives.forEach(dir => {
const control = dir.control as FormControl;
if (control.updateOn === 'submit' && control._pendingChange) {
dir.viewToModelUpdate(control._pendingValue);
control._pendingChange = false;
}
});
}
which updates a model at last.
So, in your case, just remove (click)="onSubmit()" from the submit button:
<button type="submit">Next</button>
also you do not need required DOM element property on your input, since you set it using Reactive Forms API validators: Validators.required and since you set your form to novalidate which cancels HTML5 form validation.

asyncValidation on key strokes and throttled (not on blur)

The redux-form asyncValidation is great but it only works on blur. Is it possible to make it happen during key presses, and throttled? So it runs only every 300ms and on final value?
Is it possible? The short answer is yes.
Is it tricky? Well, as you mentioned, theres the fact that the asyncValidation for redux-form option only works for the onBlur and you'd instead want it to work onChange.
So you could fork and add this feature into redux-form, so you can do this:
#reduxForm({
form: 'login',
asyncValidate: validator,
//asyncBlurFields: ['username','password'],
asyncChangeFields: ['username','password'], /* add this new option */
})
For the deboucing part, you'd want to somehow debounce the onChange handler rather than the validate function itself, which brings up another option...
redux-form exports its internal action creators which may be enough to hack it together. Particularly, there's the stopAsyncValidation action creator that lets you pass field-level async errors directly into a form. Pair that with the onChange prop for Field, and you actually have the right pieces to get it done like this:
import React from 'react'
import { Field, reduxForm, stopAsyncValidation } from 'redux-form'
import _debounce from 'lodash.debounce'
import renderField from './renderField'
#reduxForm({form: 'debouncedOnChangeValidation'})
class DebouncedOnChangeValidationForm extends React.Component {
customValidate = () => {
const { form, dispatch } = this.props
dispatch(stopAsyncValidation(form, { username: "thats wrong..." })) /* pass in async error directly! */
}
debounceValidate = _debounce(this.customValidate, 1000) /* decorate with debounce! */
render() {
const { handleSubmit, pristine, reset, submitting} = this.props
return (
<form onSubmit={handleSubmit}>
<Field name="username" type="text"
component={renderField} label="Username"
onChange={this.debounceValidate} /* bind validation to onChange! */
/>
<div>
<button type="submit" disabled={submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
</div>
</form>
)
}
}
Additionally, to access the form values for performing validation, you'd need to use the getFormValues selector.
Of course this won't be as robust as a more built-in solution, but it may work well enough for some use cases.

Focus on the form field after submit

How can I focus on a particular form field after a form submission?
Things already tried:
1.
dispatch(focus('fieldRefName'))
2.
componentWillReceiveProps = (nextProps) => {
if (nextProps.submitting) {
this.refs.fieldRefname.focus()
}
}
I also want to clean the form too after submission.
redux-form version: 3.0.12
The focus() action has no effect on the DOM. It's a reaction to the onFocus event from the DOM. You will need to use this.refs.myField.focus().
To clean the form, after submit...
<form onSubmit={this.props.handleSubmit(values => {
return doSubmit(values).then(() => this.props.reset())
}}>
...
</form>

Resources