i have an input element in a component like so :
<input #inputDate
(blur)="realDate(inputDate.value); inputDate.value='' ">
and then i want to use (show) the value of the inputDate on another component, how can i do it?
im new to angular, any help will be appreciated.
If you want to send it to a parent component, bind it to a ngModel and use event emitter to send this value.
If you want to send it to child component, use #Input decorator. (parent-to-child)
However, as you want to send the value from html, you can use jquery or document.querySelector to get the value
This might help you
If you want to send your component to a parent component, you can use the #Output() decorator and an Event Emitter together to send the value to a parent component by doing something like:
#Output()
public input: EventEmitter<string> = new EventEmitter<string>();
<my-input (input)="onInputChange()"></my-input>
// Method to detect for changes on #myInput
public onMyInputChanges(): void {
// ...
input.emit(<#myInputValue>);
}
I'll leave it as an exercise for you to figure out how to detect changes to your input element above.
If you want to send your value to a child component, you can use the #Input() decorator and pass it along as such:
<input #myInput [(ngModel)]="inputValue">
public inputValue: string = '';
<child-component [value]="inputValue"></child-component>
Because you want to use the value directly from the HTML, consider using the #ViewChild decorator which would allow you to use your local reference #inputDate to get the value, like so:
#ViewChild('inputDate')
public myInput: HTMLInputElement;
And then you can access your value through myInput.value and either use it on your component or pass it around with the above methods.
You can also look into using Services which might help you reuse some of this logic across several components if that's your use case (e.g. emitting the value from a Subject and having multiple components listen to changes on your input).
Related
I have parent and child components.
I want to send form's values from parent to child component.
Child component can do everything with this data, but all changes are local and should not be returned back to parent component.
When i send a simple variable to child comp – everything works fine and changes doesn't returned back to parent.
But when i send form's values – all changes returns back to parent component...
Live
https://stackblitz.com/edit/angular-dvqyjr
Parent Component JS
export class AppComponent {
constructor (private formBuilder: FormBuilder){};
simpleVariable = 'Value';
form: FormGroup = this.formBuilder.group({
id: 1,
name: 'Name'
});
Parent Component HTML
<hello [simpleVariable]="simpleVariable" [form]="form.value"></hello>
Child Component JS
export class HelloComponent {
#Input() simpleVariable;
#Input() form;
}
Child Component HTML
<input [(ngModel)]="simpleVariable">
<input [(ngModel)]="form.name">
Question
So how can i send an object to child component and modify it without returning data to parent?
This is quite simple. The reason for this behavior is that the form.value is an object. Meaning that you're sharing a reference object with parent and child. Meaning that any change to this object will result in a change in both parent and child.
In order to make changes in child that won't affect your parent, create a deep copy of your object using Object.assign function and use it in your child component.
export class HelloComponent implements OnInit {
_from: {};
#Input() simpleVariable;
#Input() form;
ngOnInit() {
this._form = {};
Object.assign(this._from, this.form);
}
}
Forked and edited example
From the Angular documentation at Reactive Forms - Step 2: Associating the FormGroup model and view:
A form group tracks the status and changes for each of its controls, so if one of the controls changes, the parent control also emits a new status or value change.
You can try the following one with the form:
<form [formGroup]="form">
<input formControlName="name">
</form>
It all comes to Explaining Value vs. Reference in Javascript as well as Angular's Change Detection
Overall, #benshabatnoam already answered you'r question - in order to execute change detection - you need to change object reference, either by old fashioned way:
Object.assign(this._from, this.form);
Or ES6 way:
this._from = {...this.form}
I am trying to implement two way data binding in angular components. Currently its in a parent child mode.
parent.component.html
<child [(title)]="title"></child>
<span style="color: red">This is parent component {{title}}</span>
parent.component.ts
title = 'app';
child.component.html
<span style="color: blue">This is child component {{title}}</span>
child.component.ts
#Input() title: any;
#Output() pushTitle = new EventEmitter();
constructor() { }
ngOnInit() {
this.title = 'new title';
this.pushTitle.emit(this.title);
}
The title should implement on the parent component as well, when I change it from the child. Also, I am not sure why the parent code keeps going in a loop for no reason. I have added text in html just to test if its updated in both the components, but its updating only in the child, and not in the parent. I am coming from the angularjs background, and two way data binding worked seamlessly in it. I am just confused what I am doing wrong(I know its a noob question).
Demo here: https://stackblitz.com/edit/angular-xttmxg
There is another way that you can achive the same.
#Input() title: any;
#Output() titleChange: EventEmitter<any> = new EventEmitter<any>();
changeValue() {
this.title= !title;
this.titleChange.emit(this.title);
}
Have a look at Angular documentation about two way binding
Two way data binding only works for template - component interaction.
If you want to send title change to parent component, you should do something like this:
Parent template and component:
<child [title]="title" (pushTitle)="onTitleChange(value)"></child>
<span style="color: red">This is parent component {{title}}</span>
onTitleChange(value) {
this.title = value;
}
Followup question:
Template:
<input [(ngModel)]="inputModel">
Component:
inputModel: string;
Now, every time you type something into input field you will see changes in component model, OR when change inputModel value programmatically, you will see the change in HTML input.
You are somehow creating an infinite update cycle using the 2-way-binding. This leads to the infinite loop and eventual stack overflow you noticed.
To fix this, preferably, you want to add some logic to the titleChange event (this is the banana-part of the banana-in-a-box syntax, i.e. the part in parens in [(title)] which is getting automatically translated into an event emitter named titleChange).
For example, you might want to skip updating the title property of the parent component if its equal to the update emitted by the child component.
This means you should split up [(title)] into (titleChange)="titleChange($event)" and [title]="title". The first part lets you pass the updated title as $event and then process it in a function titleChanged (name is arbitrary in this case). The second part has the effect that the child component receives updates of the parent component's title property.
Another common pattern is to make title private (commonly with a prefixed underscore, e.g. _title) and then add a getter get title() { return this._title;} so that you can (1) encapsulate this property and (2) add some processing.
In your case this is not needed, but it doesn't hurt either. ;-)
Here's a plunkr containing these changes.
I am having a child component which emits data through event emitter.The Emitting data is bind with ngModel in parent. And the emitting method in it is called from parent component.
I have created child component because i am having two same form. So i created a single form component and used it twice and binded with their data.
//Child Component Code
import {Component, EventEmitter, Input, Output} from 'angular2/core'
#Component({
selector: 'child-component',
template: `
<input [ngModel]="formObj.title" >
`
})
export class ChildComponent {
#Input() formObject: Object;
#Output() formObjectChange= new EventEmitter();
emitChangeforParent() {
this.formObjectChange.emit(newValue);
}
}
//Parent Component
#Component({
selector: 'parent-component',
template: `
<child-component[(formObject)]="doseObject1" #firstForm></child-component>
<child-component[(formObject)]="doseObject2" #secondForm></child-component>
<button (click)="save()">Save</button>
`
})
export class ParentComponent {
doseObject1 ={title:''};
doseObject2 ={title:''};
save(){
this.firstForm.emitChangeforParent();
this.secondForm.emitChangeforParent();
console.log(this.doseObject1); //Updated data by child is available.But this works when i used single tag.
But when i use multiple child tag it does not work
}
}
Problem is that whenever I use single form tag it works fine. The update done by child is reflected here in parent.
But when i use same tag tag twice, than on calling its child emitChangeForParent() method does not work.
I think you might be a little confused about how emitChangeForParent should work. This kinda of method would usually be called by the child, and used by the parent.
so the child component would have (change)="emitChangeForParent() , then on the parent you you would have
basically this means whenever the child component calls emit, it passes the data up, and the parent component can catch it by having a callback.
However, In this case I dont think you need to do that. This is most useful for value types like numbers. If you are passing in an refence type, like your json object doseObject1 ={title:''}, the parent object should still have an up to date reference to it.
I think all you need to do to make this work is have you child component template be "" with the banana in the box double binding syntax. Then the parent will still always have an accurate value of doseObject1.title and doseObject2.title
There is no need to emit the data. The double binding syntax returns the changes done in child component to parent component.
I imagine I may be missing something really obvious, however this is my situation - I have some data that is being assigned to the ngModel input of a component, e.g:
Typescript:
SomeData = {
SomeValue: 'bar'
}
Fragment of view template:
<foo [(ngModel)]="SomeData.SomeValue"></foo>
Component:
import { Component, OnChanges, SimpleChanges } from '#angular/core';
#Component({
selector: 'foo',
template: `<input type="text" [ngModel]="value" (ngModelChange)="modelChange($event)
(change)="elementChange($event)"/>`
})
export class FooComponent {
ngOnChanges(changes: SimpleChanges) {
// Fired when #Input members change
}
modelChange(value) {
// Fired when a change in the HTML element will change the model, *not* when the model changes from elsewhere
}
elementChange(event) {
// Fired when the HTML element value changes
}
}
As per my comments in the example, I'm able to tell when Inputs change, when the value of the HTML element will change the model, and when the value of the HTML element changes.
I want to be able to know from within the component, when the property that is assigned to ngModel in the view template (i.e. SomeData.SomeValue) changes. I know that Angular does this itself, because it updates the value in the HTML, however I'm at a loss as to how to intercept this change as well, from within the component, so some other action may be taken.
SomeData.SomeValue is not controlled by angular, all you do is tell angular to bind to a property and bind to an event. Angular will then run it's own change detection mechanism which will update the view. If you are interested in how Angular does this take a look at this blog.
If you want to be notified of changes to SomeData.SomeValue you'll have to set up your own system, this can be as simple as a callback or a pub/sub. But it's really too broad to go into here.
I have a angular 2 page where i need to show 2 different components using same array of data from external API. Parent is regular component, and child is shared among several other components using same functionality.
In parent component class i have output property declared:
public weatherList: WeatherForecast[];
#Output() public weatherListData: any;
Inside constructor of parent component, i populate weatherListData property with data from an external API
http.get(url)
.subscribe(result => {
this.weatherList= result.json() as WeatherForecast[];
this.weatherListData = this.weatherList;
});
and i'm using it inside parent template with success, something like: {{ weatherList.someValue }}
Also, inside parent component template, i have a call to a child component
<daily-temperature-chart [weatherListData]='weatherListData'></daily-temperature-chart>
In child component class i have declared property
#Input() weatherListData: any;
but, when i try to access weatherListData property in constructor, or init of child component, i get undefined result.
EDIT: I have played with console.log() and noticed that child component Constructor and OnInit() methods return before http.get() from parent component. Maybe this is problem, but i'm still new to angular and can't tell.
Can someone point me how to solve this?
You've a service call so you can't go for constructor or OnInit because component initialization is not dependent on your service call for this situation angular provides OnChanges whenever your input value is updated OnChanges fired.
ngOnChanges(changes: any){
console.log(changes);
console.log(this.weatherListData);
}
OnChanges passes as well an argument which informs about the current state and pervious state now you are able to use input values. If your components are bases on input and input is based on any other operation you can handle it in this block.