I have two functions with same names. One inside child class and one inside parent.
I thought If i call method in parent class that parent's function will be invoked.
But it looks it doesn't work like this and invokes child function.
So my question is how to invoke parent function in parent class if i have another with same name in child class.
I would like to get 'Parent' and 'Child', but i get 2 times 'Child'
class Parent {
constructor() {
this.init()
}
init() {
console.log('Parent');
}
}
class Child extends Parent {
constructor() {
super();
this.init()
}
init() {
console.log('Child');
}
}
new Child();
this is referring to the child instance, and inherits its .init method that shadows the .init method inherited from the parent. To refer to that explicitly, you'd write
class Parent {
constructor() {
Parent.prototype.init.call(this)
}
init() {
console.log('Parent');
}
}
But this is a really bad idea, both to override a method where the overriding one shouldn't be called, and in general to call overrideable methods in the constructor. In your case, just do all your work inside your constructor instead and drop the init method altogether.
As parent constructor call init() already, child constructor should not call init() any more.
Instead, child init() can optionally call parent init().
Related
I wish to access a parent instance from a child instance:
class Child {
constructor(props) {
// how do I access the parent Container instance from here?
}
}
class Container {
childInstance = new Child()
}
I cannot find a clean way to do this. The best way I found was to pass this to the child instance: new Child(this), but I find it heavy. Is there a simpler way that would not require me to manually pass this to every child I instanciate? Something like this for example:
class Child {
constructor(props) {
this.parent
}
}
The following defines, creates and finally inserts an instance of my "autonomous custom element" onto the container:
class MyCustomElement extends HTMLElement {
static get elementName() {
return 'my-custom-element';
}
constructor() {
const self = super();
let _myPrivateData = 'privateValue';
// the following does not cause the callback to be invoked at all!
MyCustomElement.prototype.connectedCallback = function() {
console.log('connected!');
};
return self;
}
//// this would've got invoked anyways, but there's no access to the `_myPrivateData`
// connectedCallback() {
// console.log('connected!');
// }
}
let myCustomElementName = MyCustomElement.elementName;
customElements.define(myCustomElementName, MyCustomElement);
let myCustomElement = document.createElement(myCustomElementName);
let container = document.getElementById('container');
container.appendChild(myCustomElement);
<div id="container"></div>
I've defined the connectedCallback inside of the "constructor" to have access to _myPrivateData, but then the callback does not get invoked at all! Having the identical code-excerpt immediately after the "class body" does cause the callback to be invoked in expense of not having access to _myPrivateData.
Why is that? How shall I approach the issue to have access to _myPrivateData (preserving its "private" nature) and have the callback invocation working?
Because of the Custom Element implementation you must define all the callbacks before the elemennt is defined with customElements.define(). These callbacks are readonly.
To deal with private values, you could define you own custom callback that would be invoked by the standard connectedCallback() method.
See the example below:
class MyCustomElement extends HTMLElement {
constructor() {
super()
let _myPrivateData = 'privateValue'
// the following does not cause the callback to be invoked at all!
this.connectedCallback = function() {
console.log('connected! : ' + _myPrivateData )
}
}
connectedCallback() {
this.connectedCallback()
}
}
customElements.define('my-custom-element', MyCustomElement)
<my-custom-element></my-custom-element>
Update
Effective lifecycle callbacks are actually readonly / frozen. You cannot modify them once the custom element is defined.
Consider that, when you call customElements.define(), the lifecycles callbacks are copied to the Custom Element Registry, from the class callback entries with the same name, or set to void() if the callback name doesn't exist.
When an instance of the custom element is created, these are the callback copies that are called, not the callback class prototype methods. You cannot access and therefore modify these copies.
You can still modifiy the class callbacks (the prototype entries) but it won't affect the custom element lifecyle.
The will enforce the consistancy of the life cycle for all the same custom element instances.
I have 2 components, one parent and one child, I would like to send the value of a variable to the parent component, I tried the code below but without succeed. The child component is sent the information correctly, but the parent is not receiving, looks like the function in the parent component is not identifying the receiving of the data to be triggered.
child component
...
private elements:any;
#Output() element = new EventEmitter<any>();
constructor() {
}
ngOnInit() {
this.sendContent();
}
sendContent() {
this.elements = "hi";
console.log("sended");
console.log(this.elements);
this.element.emit(this.elements);
//the function is activated and I can see the return in the console
}
parent component
...
constructor() {
}
ngOnInit() {
}
receiveContent(elements) {
console.log("received");
console.log(elements);
//the function is not activated when the child component is sent the data
}
Parent template
<app-child (sendContent)="receiveContent($event)"></app-child>
Thanks.
Inside parentheses you should put the name of the property that is decorated with #Output decorator. In this case (element)
Change your parent.html to this:
<app-child (element)="receiveContent($event)"></app-child>
In your parent component you need to bind to correct event from your child component.
In your child component you declared Output() called element so in this case the correct event name to use in the parent component will be element
Correct code will be:
<app-child (element)="receiveContent($event)"></app-child>
Official Angular Documentation - Component Interaction
How can I execute a function that is aware of a newly created class's name which is derived from a certain parent at the time that the class is extended?
What I currently do:
class component {
constructor() {
// this.constructor.name returns the derived class name on instantiation
// we need to register class components derived from component
registerIfUnknown(this.constructor.name);
}
}
However this means the registerIfUnknown function will be called every time we create a new instance of any subclasses of component. Is there a way to execute a method/function that understands what the class's name is whenever the component class is extended?
Referenced:
Override constructor with an class decorator?
http://blog.wolksoftware.com/decorators-metadata-reflection-in-typescript-from-novice-to-expert-part-ii
I'd like to wrap a classes constructor with a custom one when applying a method decorator (ie in the same way you could do with a class decorator). I require this as I have another component that will call into the class, and will execute the method that was decorated. Its not hard to have the component execute the method that was decorated, however because the decorator is run before the class is instantiated the decorated method will not be associated with a class instance and therefore will not have access to any of the classes state (ie this == undefined). So I want to be able to provide the method reference to the component during class instantiation (ie constructor) so that it is bound to the current instance.
So I'd like to do this (typescript):
class Foo {
constructor(private value) { }
#execute
bar() {
return this.value;
}
}
Which would have the same affect as doing this:
class Foo {
constructor(private value) {
StaticComponent.AddReference(this.bar().bind(this));
}
bar() {
return this.value;
}
}
If my other component has a reference to bar() it should be able to execute it with bar having full access to its instance.
I've tried to override the prototype of the target etc in a similar way you might do so for a class decorator, but couldn't get that to work.