Angular 5 bind date to field (reactive forms) - javascript

I've got a problem with input type date. I want to bind data from component. Here's my field:
<div class="col-md-6">
<label for="dateOfReport">Data zgłoszenia błędu:</label>
<input type="date" formControlName="dateOfReport" id="dateOfReport" class="form-control" [value]="report.dateOfReport | date:'dd.MM.yyyy'"> {{report.dateOfReport | date:'dd.MM.yyyy'}}
</div>
Here's how variable dateOfReport look:
new Date().toJSON().slice(0, 10)
Where I fail? {{ .. }} shows good date, but my field doesn't take it as default.

When using Reactive Forms, you should not bind data directly to the control, instead use setValue() or patchValue() of FormGroup.

I found an answer to bind the date to the input when creating a form using reactive forms.
I'm using Angular 11.
Here is the HTML
<div class="form-group">
<label for="dateOfReport">Report Date</label>
<input type="date" class="form-control" name="dateOfReport" id="dateOfReport" formControlName="dateOfReport" />
</div>
And here is my angular component
// ...other imports
import { formatDate } from "#angular/common";
// ...
//... creating the form
this.form = this.formBuilder.group({
dateOfReport: [formatDate(new Date(), "yyyy-MM-dd", "en"), [Validators.required]],
// other form fields
});

Related

Value change for Ng Date Time Picker doesn't work

Nothing of events are not working for ng-pick-datetime
<label class="fieldlabel">{{ attribute.attribute.displayName }}: </label>
<label>
<mat-form-field class="field-full-width">
<input [owlDateTimeTrigger]="datePicker" placeholder="Date" [owlDateTime]="datePicker"
[dateTimeInput]="emitValue()" [(ngModel)]="value.value">
<owl-date-time #datePicker></owl-date-time>
</mat-form-field>
</label>
Also I import needed modules:
import { OwlDateTimeModule, OwlNativeDateTimeModule } from 'ng-pick-datetime';
https://www.npmjs.com/package/ng-pick-datetime
I have the same errors for other events: afterPickerOpen,
yearSelected, monthSelected, dateTimeChange
dateTimeInput is an output (event) not an input. Hence, you need to use () instead of [].
(dateTimeInput)="emitValue()"
For further information on outputs, read the official Angular docs.

Disable a sibling button if reactive form field is not valid Angular 5

I have a component with a reactive form in it like so...
form component.html
<form [formGroup]="form" class="do-form">
<div formGroupName="dot">
<div class="do-form__container">
<div class="do-form__group">
<label for="day">Day</label>
<input id="day" type="number" placeholder="XX" class="do-form__group__control" formControlName="day" />
</div>
<div class="do-form__group">
<label for="month">Month</label>
<input id="month" type="number" placeholder="XX" class="do-form__group__control" formControlName="month" />
</div>
<div class="do-form__group">
<label for="year">Year</label>
<input id="year" type="number" placeholder="XXXX" class="do-form__group__control" formControlName="year" />
</div>
</div>
<div class="do-form__errors" *ngIf="isValid()">
<p>Please enter a valid date</p>
</div>
</div>
</form>
and in my form.component.ts
form = this.fb.group({
dot: this.fb.group({
day: ['',
[
Validators.required,
Validators.min(1),
Validators.max(31)
]],
month: ['',
[
Validators.required,
Validators.min(1),
Validators.max(12)
]],
year: ['2018',
[
Validators.required,
Validators.min(1918),
Validators.max(2018)
]]
})
});
isValid() {
return (
!this.form.valid &&
this.form.get('dot.day').touched &&
this.form.get('dot.month').touched &&
this.form.get('dot.year').touched
);
}
Now I have a separate page (app.component.html) like so
<app-form #formTool></app-form>
<button class="full-width-btn" (click)="next(); form.sendResult();">SEND</button>
app.component.ts
import { formComponent } from '../form-component/form-component.ts'
export ...
#ViewChild(formComponent) form;
Now basically I want to disable the send button until the form in the app form component is valid.
I'm not entirely sure how to do this. I thought about storing a valid event on a shared server but I'm not sure how I can store a valid event in a service. I saw that with non-reactive forms you can just have a button that uses the same ngModel but once again not sure if that would work in this case.
Any help would be appreciated!
EDIT
I have tried [disabled]="form.invalid" and [disabled]="!isValid()" but I am still able to click the button
I have also tried using [disabled]=!form.isValid() and [disabled]=!form.form.isValid()
Thanks
You are really close. Here is the only thing you need to add:
<app-form #formTool></app-form>
<button class="full-width-btn" [disabled]="!isValid()" (click)="next(); form.sendResult();">SEND</button>
In form component you could define an event #Output formValid = new EventEmitter().
Then you can listen to changes in input fields (on keypress or so) and on any change check the validity and if the form is valid, emit an event: formValid.emit().
In the app component define formIsValid = false, and on the app-form element you can listen to the formValid event:
< app-form (formValid)="formIsValid = true">
(or some function in app.component.ts instead of the inline code).
And finally on button
< button [disabled]="!formIsValid">

ng-maxlength not working

I have an Angular 4 Application. I am trying to add validation to form inputs, where inputs with numbers should not accept more than 4 digits. If more, it should invalid the form. I am using reactive forms. This is the code.
<input class="form-control form-control-amount no-z-index"
id="forNumber"
name="forNumber"
formControlName="forNumber"
ng-required="true"
type="number"
ng-maxlength="4"
[(ngModel)]="saveNumber"
[attr.disabled]="!condition? 'disabled': null "
#forNumber
>
<small class="alert alert-danger" *ngIf="!form.get('forNumber').valid">
Invalid input.
</small>
If I enter 11111 it should invalid the entry and should print above alert message; which is not happening.
Any idea what's going wrong here? Thanks.
First, you don't use a ngModel and a formControlName together. And I don't know about the ViewChild reference, and what you do with it, but if it's only to get the value, then you don't need it either.
Second, ng- is AngularJS, not Angular.
Third, you need to add a validator to you control.
<input class="form-control form-control-amount no-z-index"
id="forNumber"
name="forNumber"
formControlName="forNumber"
ng-required="true"
type="number"
maxlength="4"
[attr.disabled]="!condition? 'disabled': null "
>
Now, to add the validator, in your TS
constructor(private FB: FormBuilder) {
this.myForm = FB.group({
forNumber: ['', [Validators.maxLength(4)]]
});
}

Vue.js: Calling function on change

I'm building a component in Vue.js. I have an input on the page where the user can request a certain credit amount. Currently, I'm trying to make a function that will log the input amount to the console, as I type it in. (Eventually, I'm going to show/hide the requested documents based on the user input. I don't want them to have to click a submit button.)
The code below logs it when I tab/click out of the input field. Here's my component.vue:
<template>
<div class="col s12 m4">
<div class="card large">
<div class="card-content">
<span class="card-title">Credit Limit Request</span>
<form action="">
<div class="input-field">
<input v-model="creditLimit" v-on:change="logCreditLimit" id="credit-limit-input" type="text">
<label for="credit-limit-input">Credit Limit Amount</label>
</div>
</form>
<p>1. If requesting $50,000 or more, please attach Current Balance Sheet (less than 1 yr old).</p>
<p>2. If requesting $250,000 or more, also attach Current Income Statement and Latest Income Tax Return.</p>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'licenserow',
data: () => ({
creditLimit: ""
}),
methods: {
logCreditLimit: function (){
console.log(this.creditLimit)
}
}
}
</script>
If I change methods to computed, it works - but I get an error saying Invalid handler for event: change every time it logs the value.
Use the input event.
<input v-model="creditLimit" v-on:input="logCreditLimit" id="credit-limit-input" type="text">
change only fires when the element loses focus for input elements. input fires each time the text changes.
Binding #input event alongside with v-model is unnecessary. Just bind v-model and thats all. Model is automatically updated on input event.
new Vue({
el: '#app',
data: {
message: ''
}
})
<script src="https://unpkg.com/vue#2.4.4/dist/vue.min.js"></script>
<div id="app">
<input type="text" v-model="message"><br>
Output: <span>{{ message }}</span>
</div>
And if you need log it on change to console, create particular watcher:
new Vue({
el: '#app',
data: {
message: ''
},
watch: {
message: function (value) {
console.log(value) // log it BEFORE model is changed
}
}
})
<script src="https://unpkg.com/vue#2.4.4/dist/vue.min.js"></script>
<div id="app">
<input type="text" v-model="message"><br>
Output: <span>{{ message }}</span>
</div>
<input v-model="yourVariableName" #input="yourFunctinNameToBeCall" id="test" type="text">
You can use #change to it trigger the function when is done
Ex- Select a value from drop down
But here you need to call the function when pressing keys (enter values). So use #click in such cases

Field validation onBlur with Aurelia

I'm using Aurelia and Typescript to build a web page. I have a simple login form and I'd like to validate the user email and password.
I am using Aurelia validation and by default it validates the content of my input each time it changes, which can be annoying. (ex: getting an error message saying that the email is not valid when you're not even done typing it). So I'd like to do the validation onBlur instead (when the focus on the input is lost) and when the user clicks on the Login button.
Here's my code:
login.html
<template>
<section>
<div class="container col-lg-12">
<div class="col-md-4 col-md-offset-4 centered">
<h2 t="signin_sign_in"></h2>
<form role="form" submit.delegate="login()" validate.bind="validation">
<br if.bind="errors" />
<div if.bind="errors" repeat.for="error of errors" class="alert alert-danger">
<h4 repeat.for="message of error">${message}</h4>
</div>
<div class="form-group">
<label class="control-label" t="signin_email_address"></label>
<input type="text" class="form-control" value.bind="email">
</div>
<div class="form-group">
<label class="control-label" t="signin_password"></label>
<input type="password" class="form-control" value.bind="password">
</div>
<button type="submit" class="btn btn-primary" t="signin_sign_in"></button>
</form>
</div>
</div>
</section>
</template>
login.ts
#autoinject()
export class Login {
email: string;
password: string;
router: Router;
application: ApplicationState;
accountService: AccountService;
errors;
validation;
i18n: I18N;
constructor(router: Router, application: ApplicationState, accountService: AccountService, validation: Validation, i18n: I18N) {
this.router = router;
this.application = application;
this.accountService = accountService;
this.i18n = i18n;
this.errors = [];
this.validation = validation.on(this)
.ensure('email')
.isNotEmpty()
.isEmail()
.ensure('password')
.isNotEmpty()
.hasLengthBetween(8, 100);
}
navigateToHome(): void {
this.router.navigate("/welcome");
}
login(): void {
var __this = this;
this.validation.validate()
.then(() => this.accountService.signin(this.email, this.password, this.rememberMe)
.then(result => {
// Do stuff
})
.catch(error => {
// Handle error
}
}));
}
}
My first thought was to add
& updateTrigger:'blur':'paste'
to my binding in the HTML, but it doesn't work. The binding is updated correctly when focus is lost but the validation stops working. There's no error in the Chrome debug console either.
Any idea on how to do this? Is is possible at all?
There's different binding behaviours you can use to tell when the validation should trigger. You can read more about them in the Aurelia docs on validation.
From the docs;
The validate binding behavior obeys the associated controller's
validateTrigger (blur, change, changeOrBlur, manual). If you'd like to
use a different validateTrigger in a particular binding use one of the
following binding behaviors in place of & validate:
& validateOnBlur: the DOM blur event triggers validation.
& validateOnChange: data entry that changes the model triggers validation.
& validateOnChangeOrBlur: DOM blur or data entry triggers validation.
& validateManually: the binding is not validated
automatically when the associated element is blurred or changed by the
user.
I recently encountered this exact use case and I solved it using Aurelia's built in debounce feature.
<input type="text" class="form-control" id="email" placeholder="Email"
value.bind="email & validateOnChangeOrBlur & debounce:600 ">
600ms is an arbitrary value, but you can always play around with it as needed.

Categories

Resources