How to set default values for Angular 2 component properties?
That is interesting subject.
You can play around with two lifecycle hooks to figure out how it works: ngOnChanges
and ngOnInit
.
Basically when you set default value to Input
that's mean it will be used only in case there will be no value coming on that component.
And the interesting part it will be changed before component will be initialized.
Let's say we have such components with two lifecycle hooks and one property coming from input
.
@Component({
selector: 'cmp',
})
export class Login implements OnChanges, OnInit {
@Input() property: string = 'default';
ngOnChanges(changes) {
console.log('Changed', changes.property.currentValue, changes.property.previousValue);
}
ngOnInit() {
console.log('Init', this.property);
}
}
Situation 1
Component included in html without defined property
value
As result we will see in console:Init default
That's mean onChange
was not triggered. Init was triggered and property
value is default
as expected.
Situation 2
Component included in html with setted property <cmp [property]="'new value'"></cmp>
As result we will see in console:
Changed
new value
Object {}
Init
new value
And this one is interesting. Firstly was triggered onChange
hook, which setted property
to new value
, and previous value was empty object! And only after that onInit
hook was triggered with new value of property
.
Angular: How to get default @Input value?
There is no standard angular way, because many times you would want null
or undefined
as value. Your ideas are not bad solutions. I got a couple more
- I suppose you can also use the
ngOnChanges
hook for this: - Or using
Observables
: - Or create your own decorator playground
@Input()
type: string = 'defaultType';
ngOnChanges(changes: SimpleChanges): void {
// == null to also match undefined
if (this.type == null) {
this.type = 'defaultType';
}
}
private readonly _type$ = new BehaviorSubject('defaultType');
readonly type$ = this._type$.pipe(
map((type) => type == null ? 'defaultType' : type)
);
@Input()
set type(type: string) {
this._type$.next(type);
}
function Default(value: any) {
return function(target: any, key: string | symbol) {
const valueAccessor = '__' + key.toString() + '__';
Object.defineProperty(target, key, {
get: function () {
return this[valueAccessor] != null ? this[valueAccessor] : value
},
set: function (next) {
if (!Object.prototype.hasOwnProperty.call(this, valueAccessor)) {
Object.defineProperty(this, valueAccessor, {
writable: true,
enumerable: false
});
}
this[valueAccessor] = next;
},
enumerable: true
});
};
}
which you can use like this:
@Input()
@Default('defaultType')
type!: string;
How to set default value for Input Angular?
Hai you can try to set the value in ngOnInit. once the ngOnInIt is called the value for theapplicant
will be set if any provided by the parent component.
Here check if the value is undefined and if so set a default
@Input() applicant: Applicant;
ngOnInIt() {
if (!this.applicant) {
this.applicant = {
// ur defaults here
};
}
if you want to always pass proper values to children components from parent then
this.applicants.map((applicant) => {
if (!applicant || !applicant.representative) {
applicant = {
// your defaults here
};
this.representativeAdapter.adapt(applicant.representative);
...
How to set default parameter for @Input in Angular2?
try
@Input() name: string = 'noname';
Angular setting a default number value
No need for value="1"
. Just in your .ts
do this:
ngOnInit() {
WorkItemSelection.CopyQuantity = 1;
}
Not able to set default value of input (Angular)
You are using FormBuilder
and as such the value
property of input
is not used. The initial value is initialized by the FormControl
Remove the following from the constructor
this.updateForm = this.formBuilder.group({
nomeUpdate: this.formBuilder.control("")
})
Modify getCliente()
getCliente(){
this.userService.getUser(localStorage.getItem('userAtual'))
.pipe(first()).subscribe(user => {
this.cliente = user[0];
this.updateForm = this.formBuilder.group({
nomeUpdate: this.formBuilder.control(this.cliente.nome)
})
});
}
Have added .pipe(first()) so only first value received is used.
Hope it helps!
(ngModel)] input with default input values
<input [(ngModel)]="message.name" name="name" class="input" type="text" required>
In your component :
message : any = { name: 'YOUR_DEFAULT_VALUE', }
Angular: Setting an emptied string to a default value does not update the bound text field properly if the field previously had the default value
Inherent error
The ngModel
directive uses @Input
and @Output
to obtain the value and emit the change event. So binding a function like setter or getter to a directive like [ngModel]
with default change detection strategy would trigger the function for each change detection.
To replicate this error, plug in a console.log
in the getter, type some value and keep pressing backspace in the <input>
and let go. You could see the console.log
messages keeps getting printed.
Error replication: Stackblitz
Why isn't 'DEFAULT' inserted on Ctrl+a+Backspace
As said before, the ngModel
directive uses @Input
and correspondingly the ngOnChanges()
hook to fetch any changes to the value from <input>
tag. One important thing to note is ngOnChanges()
won't be triggered if the value hasn't changed(1).
We could try to split the two-way binding [(ngModel)]
to [ngModel]
input and (ngModelChange)
output.
export class AppComponent {
public testString: string;
onChange(value: string) {
this.testString = value === '' ? 'DEFAULT' : value;
}
}
<input type="text" [ngModel]="testString" (ngModelChange)="onChange($event)" />
Still error prone: Stackblitz
Here the Ctrl+a+Backspace any string other than 'DEFAULT' would insert 'DEFAULT' as expected. But Ctrl+a+Backspace 'DEFAULT' would result in empty <input>
box due the ngOnChanges()
issue discussed above.
Solution
One way to achieve expected behavior is to not depend on the ngModel
directive's ngOnChanges()
hook to set the value, but to do it ourselves manually. For that we could use an Angular template reference variable in the <input>
and send it to the component for further manipulation.
export class AppComponent {
public testString: string;
public onChange(value: string, inputElem: HTMLInputElement) {
this.testString = value === '' ? 'DEFAULT' : value;
inputElem.value = this.testString;
}
}
<input
type="text"
#myInput
ngModel
(ngModelChange)="onChange($event, myInput)"
/>
Working example: Stackblitz
Here the #myInput
is the template reference variable. If this feels hacky, you'd need to know using ngModel
to manipulate <input>
is in itself called template driven forms. And it's quite legal to manipulate the template ref directly.
With all that said, IMO in cases where such input manipulation is needed, I'd recommend you to use the Angular Reactive Forms instead. It provides a more granular control over the input.
(1) The ngOnChanges()
won't be triggered if the previousValue
and currentValue
of the respective @Input
variable's SimpleChange
object hasn't changed.
Angular: How to set input to its default value
What you need is reference to the form in order to have easier access to all controls within that form.
For that reason I added reference to the form and ngSubmit
.
<form (ngSubmit)="adicionar(f)" #f="ngForm">
...
</form>
With this in your adicionar
method within component class you have access to all values of the form along with access to resetForm
method which resets form data along with touched
and dirty
flags.
Another important is checks of errors and deciding when to show them. Usually you want to do that when form is submitted or field has been touched/dirty.
Example:
<small
*ngIf="Tipo.invalid && (f.submitted || Tipo.touched || Tipo.dirty)"
class="invalid-feedback">
<span *ngIf="Tipo.errors.required">Tipo is required</span>
</small>
Supporting documentation
https://angular.io/guide/form-validation#template-driven-validation
Working StackBlitz -> https://stackblitz.com/edit/angular-nk6zga
Related Topics
How to Completely Remove Ionic and Cordova Installation from Mac
How to Push Array to Json Object in Angular
How to Make Select Option Disable
How to Remove Captcha Verification from Firebase Phone Auth Using JavaScript
Expand Div on Click With Smooth Animation
How to Strip/Replace Something from a Url
Connecting to Tcp Socket from Browser Using JavaScript
Possible to Detect If a User Has Multiple Tabs of Your Site Open
Vuejs Set Active Class, When One Li Element Clicked in V-For Loop
Window.Scroll Smooth Not Working on Safari
Javascript - How to Remove All Extra Spacing Between Words
Sticky Header Smoothing Scroll Down
How to Remove Time from Datetime in SQL
Label and Input Fields on the Same Line
Get Part of the Url Pathname Via JavaScript Regex