Notify parent property from child which is dom-repeating - polymer

i have initialized property buyitem in the child component, and calling order function to call it.
order() { this.buyitem = "change";}
and it is changing in the component level. and in the parent component it is not reflecting. I added reflectToAttribute: true and notify:true in both components.

In order to reflect to parent value upward changes, let say you are in parent-app.html example, use {{...}} for two way data binding.( not [[...]])
<child-elem buyitem = "{{buyitem}}"></child-elem>
into child-elem element declare property notify:true will be enough:
static get properties() { return {
buyitem:{
type:String,
notify:true
}
but also use this.set instead this.buyitem = "change"
this.set('buyitem', 'change'); // to observable changes.

Related

How can I hide a HTML element on a grandfather component after a button on a grandchild component is clicked?

I have a grandfather component that shows a message saying that a field on a grandchild component must be updated.
Once the user updates the value and clicks on a button, the HTML element of the grandparent must immediately dissapear.
A simplified model of my solution is as follows:
<div [hidden]="buttonPressedOnGrandchild">
<p>You must update the field X</p>
</div>
I need to set the value of buttonPressedOnGrandchild to true from the grandchild component. Or use another solution to hide the element.
I've found solutions for parent>child and child>parent communication, but not for grandfather and grandchild ones.
The solution is a service. Use the service to set the value when the grandchild clicks and let the grandfather subscribe to the value in order to get updated, whenever it changes.
GrandfatherToGrandChildService
private buttonPressedOnGrandchild: Subject<boolean> = new Subject<boolean>();
// return the Subject as an Observable in order to be able to subscribe to it
public get buttonPressed(): Observable<boolean> {
return this.buttonPressedOnGrandchild.asObservable();
}
// set the current value
public set buttonPressed(value: boolean) {
this.buttonPressedOnGrandchild.next(value);
}
GrandfatherComponent TS
constructor(private grandfatherToGrandChildService: GrandfatherToGrandChildService){
}
ngOnInit(): void {
// subscribe to the value and refresh the local variable whenever it changes
this.grandfatherToGrandChildService.buttonPressed.subscribe( value => {
this.buttonPressedOnGrandchild = value;
});
}
GrandChildComponent TS
constructor(private grandfatherToGrandChildService: GrandfatherToGrandChildService){
}
onClick(): void {
this.grandfatherToGrandChildService.buttonPressed = true;
}

How to know google map controls creation is done?

I need to dynamically create a ui widget with a parent div.id='myDivId', which is a google map control.
var centerControlDiv = document.createElement('div');
var centerControl = new CenterControl(centerControlDiv, map);
centerControlDiv.index = 1;
centerControlDiv.id = 'myDivId';
map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
// $('#myDivId') causes exception as $('#myDivId') is not created on
// map as a DOM element yet.
var uiWidget = new uiWidget('myDivId');
// $(#myDivId) is used in class uiWidget().
class uiWidget {
constructor(divId) {
this.id = divId;
// It should fail here due to this.$div property, as
// div 'myDivId' is not a DOM element yet by google map
// controls API.
this.$div.click($.proxy(this.event_click, this));
}
get $div() {
return $(‘#’ + this.id);
}
event_click(eve) {
}
}
But, there is no event of when this parent div is created. Therefore, the child ui widget can't be created at correct time.
How to know parent div with id 'myDivId' is created?
You are trying to reference a DOM element by ID as a child of document when that element has only been created but not yet added to the document.
But you already have a reference to the #myDivId element in the centerControlDiv variable, so you don't need to use the ID to reference it. Just change this line:
$('#myDivId').append("<div>UI widget</div>");
to:
$(centerControlDiv).append("<div>UI widget</div>");
Put another way, to answer your question "How to know parent div with id 'myDivId' is created?", that div already is created - you created it in the document.createElement('div') call. It just isn't a child of document yet.
So when you use $('#myDivId'), or similar calls like document.getElementById('myDivId'), those calls can't see it. It's just a standalone element that you have a reference to, so you can access it through that element instead of looking it up in the document DOM.
Update based on your latest code:
To apply this principle to your uiWidget class, you can have the class work with the actual div element you created instead of accessing it by ID. Even better, since you're using jQuery, pass it a jQuery object from the beginning, like this:
var uiWidget = new UiWidget( $(centerControlDiv) );
class UiWidget {
constructor($div) {
this.$div = $div;
this.$div.click($.proxy(this.event_click, this));
}
// ...
}
As you can see, the code no longer requires the div ID at all, and it doesn't need the get $div() either. $div and this.$div are already a jQuery object wrapping your centerControlDiv.
I also changed the name of the class to UiWidget to follow recommended JavaScript style and avoid conflict with the uiWidget variable that holds an instance of the class.

Child component value not setting in Angular 2?

So I have my child component's value marked like so:
#Input flag;
And then in the particular method I have:
myParentComponent.flag = true;
Then in the html of the parent component I have:
<app-childComponent-template [flag] = flag ></app-childComponent-template>
I'm using Chrome's inspection tool to watch the console where I'm logging the changes. When I set the flag to true in the child component it works, however, it won't carry over to the parent component and I can't figure out why. I've gone through this documentation (https://angular.io/guide/component-interaction) multiple times but everything seems to match up accordingly.
Thank you!
The syntax [flag] indicates that it's a one-way data binding: The parent will push changes to flag to the child. But changing the child's #Input flag variable will not emit a change to the parent.
In order to do that, you need to use an #Output in the child component:
#Input('flag') flag;
#Output('flag') flagChanged = new EventEmitter<boolean>();
Then, to inform the parent that the flag has changed, emit an event from the child component:
this.flagChanged.emit(newFlagValue);
Finally, to be informed of changes in the parent component:
<app-childComponent-template [flag]="flag" (flag)="onFlagChanged($event)"></app-childComponent-template>
onFlagChanged(newValue) {
alert(`New flag value: ${newValue}`);
}

React: Cant call a function inside child component

I am trying to call a function inside child component through this.refs but i keep getting error that this function doesn't exist.
Uncaught TypeError: this.refs.todayKpi.loadTodaysKpi is not a function
Parent component:
class KpisHeader extends React.Component {
constructor() {
super();
this.onUpdate = this.onUpdate.bind(this);
}
render(){
return <div>
<DateRange ref="dateRange" onUpdate={this.onUpdate}/>
<TodayKpi ref="todayKpi" {...this.state}/>
</div>;
}
onUpdate(val){
this.setState({
startDate: val.startDate,
endDate: val.endDate
}, function(){
this.refs.todayKpi.loadTodaysKpi();
});
}
}
I want to get some data from DateRange component through function onUpdate, and then I want to trigger a function inside TodayKpi which fetches data from the server. For now it is just console.log("AAA");.
Child component:
class TodayKpi extends React.Component {
constructor() {
super();
this.loadTodaysKpi = this.loadTodaysKpi.bind(this);
}
render(){
console.log(this.props.startDate + " "+ this.props.endDate);
return <div className="today-kpi">
</div>;
}
loadTodaysKpi(){
console.log("AAAA");
}
}
How should I implement this?
For reasons I don’t yet grasp, React discourages calling child methods from the parent. However, they relent and give us an ‘escape hatch’ which allows just that. You were correct in thinking that ‘Refs’ were a part of that escape hatch. If, like me, you have read dozens of articles searching for this information, you will be well prepared to understand their description of the escape hatch
In your case, you may want to try something like this in your KpisHeader class.
Change this line
<TodayKpi ref="todayKpi" {...this.state}/>
to use a ref callback function something like this:
<TodayKpi ref={(todayKpiComponent) => this.todayKpiComponent = todayKpiComponent} {...this.state}/>
or, pre-ES6, this:
<TodayKpi
ref=
{
function (todayKpiComponent)
{
this.todayKpiComponent = todayKpiComponent
}
}
{...this.state}
/>
Then you will be able to access your todayKpi component methods from your KpisHeader class like this:
this.todayKpiComponent.someMethod();
Oddly, for me, inside the ref callback function, ‘this’ was the window rather than the parent component. So, I had to add
var self = this;
above the render method and use ‘self’ inside the ref callback function.
In my case I had an unknown number of dynamically generated children components, so I put each one into an array. I cleared the array in componentWillUpdate. It all seems to be working but I have an uneasy feeling especially given React’s distaste for calling children’s methods.
If you want the function/method to be called inside the child, you should pass it to the child from the parent to start with. The other thing that you need to change is onUpdate to onChange, assuming that you want to track every change to that field. The other alternative is to check when it is onSubmit, but it sounds like you want to have it happen every time the field is updated.

I cannot reference parent in my constructor method

public function Browser(){
var chrome:chromeicon = new chromeicon();
this.parent.addChild(chrome);
chrome.y = 745;
chrome.x = 220;
}
I notice that I cannot reference the parent of the class in the constructor method or any method that is instantiated when I add the object. There must be a way around this problem, but since I'm new to oop I don't know it.
It's because a "parent" refers to parent on list of displayed objects. It means that as long as this object is not added as a child to other object, it has no parent, I'm not sure if they need to be added to stage also. You can go around this problem by adding to constructor a listener:
this.addEventListener(Event.ADDED_TO_STAGE, _myFunction);
and then construct a function:
private function _myFunction(e:Event) :void {
this.removeEventListener(Event.ADDED_TO_STAGE, _myFunction);
// here you will be sure that your object has a parent that you can refer to, that will be a parent on the display list.
}