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}`);
}
Related
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.
I have very simple setup. When I check on checkbox, a pop up will open and ask to link to another checkbox.
When I close the popup, whatever the checkbox I selected, both will be checked.
I have array updated with checkbox value.
After I close the popup, the values are showing right in the array but not in UI. When I select other tab and get back to this tab, checkboxes are showing right.
this.fire('details', this.details);
This is not working from child page.
How can I refresh the parent element?
Above your details event, will fire an event with on-<your-custom-event> at parent element as on-details So you need to assign a listener something like at parent:
<child-element
on-details = '_detailsChanged'>
</child-element>
...
Polymer {(
_detailsChanged: function(e) {
// e.detail will give you this.details object
}
Or I assume you want to assign an object at the child and reflect observations on the parent, so at parent element :
<child-element
details = "{{details}}"
><child-element>
and at the child element, you need to notify=true this object at property declarations and notifyPath with making observable changes at parent something like:
properties: {
details: {
type:Object,
notify:true
}
}
..
this.set('details', nevDetailsValue); //Use this.set method
this.notifyPath('details'); // Than detail property will change value at parent.
EDIT : Need to specify the exact path !!
DEMO
this.notifyPath('details.<path which is changed>'); // ie:this.notifyPath('details.name')
I have created an Angular component that displays a toggle-switch. The functionalities of the switch are what I want, i.e. it switches correctly when I click on it. The only extra thing I want to add, is that the initial state is based on a boolean Input variable enableSwitch.
So when I display the toggle switch like this:
<toggle-switch [enableSwitch]="true"></toggle-switch>
I want initially the toggle being enabled (rectangle on the right). When I click on it, I want to toggle to the disabled state, and I want to return the boolean as false.
The same function applies when I want to display the toggle initially being disabled:
<toggle-switch [enableSwitch]="false"></toggle-switch>
I have created a Plunker to demonstrate the problem.
Can anyone help me further?
You can do a two-way binding approach, using ngModel.
<input type="checkbox" [(ngModel)]="enableSwitch">
To instanciate the variable as true, you could do:
#Input() enableSwitch: boolean = true;
The click event would then be obsolete.
Rememeber to include the FormsModule in app.ts.
See forked example:
https://plnkr.co/edit/TIxr6BGrXeVmPYO35DrQ?p=preview
EDIT:
In case of two-way databinding on the component - https://angular.io/guide/template-syntax#two-way-binding---
You first need the banana-in-a-box syntax:
<toggle-switch [(enableSwitch)]="enable"></toggle-switch>
Then you need to use an EventEmitter with the special variable name fooChange where foo is the #Input name.
#Output() enableSwitchChange = new EventEmitter<boolean>();
#Input() enableSwitch: Boolean = true;
Then emit the updated value when the value changes:
update() {
this.enableSwitchChange.emit(this.enableSwitch);
}
To call the update() function you can use change.
<input type="checkbox" [(ngModel)]="enableSwitch" (change)="update()">
Plunkr: https://plnkr.co/edit/Lx7QDbKt6V3HdFJN3bZx?p=preview
This can also be solved simpler without ngModel, but you probably see how yourself. =)
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.
Hello i have a function as following:
private function seatClickHandler(e:MouseEvent):void{
var check:Check = new Check();
if(e.target.contains(check)){
e.target.removeChild(seat);
}else{
e.target.addChild(check);
}
}
basicly i want to check if e.target contains a child called check. If it does i want e.target to remove the child, else i want to add the child. But the method i tried doesnt seem to work although i think this is the way to go. Any suggestions?
When you declare your Check object, Actionscript creates a reference code for that specific object.
So the first time your code is run, your Check object could be given a reference of #c0ecc29. Your if statement checks to see if #c0ecc29 is a child component of target. It won't be, so the Check object with reference #c0ecc29 is added to target.
The second time the clickHandler is called, a new instance of the Check object is created which will have a new reference id. Your target has the original Check object with the #c0ecc29 reference so it won't get removed.
The correct way to get this working depends on what target is (DataGrid, Group, etc.).
EDIT:
Based on your comments, I would try something like this. It checks to see if the Check object is a child of target and adds it if needed. Then when the Check object is clicked, it will toggle its visibility.
public var check:Check = new Check();
private function seatClickHandler(e:MouseEvent):void
{
if(!e.target.contains(check))
{
check.addEventListener(MouseEvent.CLICK, check_handleClick);
e.target.addChild(check);
}
}
protected function check_handleClick(event:MouseEvent):void
{
check.visible = !check.visible;
}
If you need to actually remove the Check object from target instead of just changing its visibility, you could try this:
public var check:Check = new Check();
private function seatClickHandler(e:MouseEvent):void
{
if(!e.target.contains(check))
{
e.target.addChild(check);
}
else
{
e.target.removeChild(check);
}
}
If the child is named 'check' then you should be able to use getChildByName(). See flash.display.DisplayObject.name
If you happen to have the child in memory, you can use getChildIndex()
check is a new object in the scope of that function, so it will not be a child of the event target.
What you want to do is declare check as a global variable (And also cast target as DisplayObjectContainer).
e.g.
private function seatClickHandler(e:MouseEvent):void{
if((e.target as DisplayObjectContainer).contains(check)){
(e.target as DisplayObjectContainer).removeChild(seat);
}else{
(e.target as DisplayObjectContainer).addChild(check);
}
}
However I'm not sure if this is exactly what you want to do (There can only be one check). A better approach would be to have a function (maybe toggleCheck) on the target, and have that display object responsible for rendering the check (And removing it)
This worked perfectly fine for me in my situation:
if(possibleChild.parent == holder)
holder.removeChild(possibleChild)
It may or may not be exactly what you're looking for.