How to call parent method inside a javascript child class - javascript

Following is the code for a vue component js file.
(assuming that the vue component js file is a Class)
export default { -----> this is the parent, it is a component & it doesn't have a name!
name: "mapping",
components: {},
props: ["data"],
data() {
},
methods: {
parentMethod() {} ---->> this is the parent method. I want to call this inside the Rect class
},
mounted() {
class Rect { -----> this is the child class,
constructor() {
this.parentMethod() // -> this is the parent method. how can I do this?
}
// call parent methods (i.e. component's) inside this class
//or something like this.
this.parentMethod() // -> this is the parent method. how can I do this?
}
}
As you can see I'm creating a class called Rect inside the mounted hook inside the vue js component class.
What I want is to call methods of the parent component inside this Rect class.
How can I achieve that?
UPDATE
I'm not extending the parent component class inside itself. I'm just defining a new class called Rect inside the parent component class.
So I don't think I can call super().
Not sure though!!
UPDATE
As I go through answers, I came to see that most of them suggests extending the class. But here the parent class doesn't have a name. It's just export default {} in vue.
& also I'm not sure whether I will be able to extend a parent inside itself to create a new class within inside itself.
NOTE
The requirement is to call the parent method from/inside a class which is the child of parent class (ie defined within the parent => defined within the parent body) Hope that makes sense!!

When you create a new class you change who this is inside that class. So you need to give that class a reference to its parent:
mounted() {
const parentRef = this; // reference to the parent instance
class Rect {
constructor() {
parentRef.parentMethod()
}
...
parentRef.parentMethod() // -> this is the parent method
}
}

Check extends and super keywords:
//Inheritance
//Parent class (superclass)
class Animal {
constructor(name) {
this._name = name;
this._behavior = 0;
}
get name() {
return this._name;
}
get behavior() {
return this._behavior;
}
incrementBehavior() {
this._behavior++;
}
}
//Child class (subclass)
class Cat extends Animal { // The extends keyword makes the methods of the animal class available inside the cat class.
constructor(name, usesLitter) {
super(name); // The super keyword calls the constructor of the parent class.
this._usesLitter = usesLitter;
}
get usesLitter() {
return this._usesLitter;
}
}
const bryceCat = new Cat('Bryce', true);
console.log(bryceCat.name); //Output: Bryce
console.log(bryceCat.usesLitter); //Output: true

In Vue you want to emit events from child components that are handled by the parent component rather than calling parent component methods directly from the child.
See https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events

Related

typescript: member variables from super class's constructor

The following code will alert undefined
class Parent {
field: string
constructor() {
alert(this.field)
}
}
class Child extends Parent {
field = 'child'
}
new Child() #=> undefined
whereas, the following alerts 'child' as expected
class Parent {
field: string
constructor() {
alert(this.field)
}
}
class Child extends Parent {
field = 'child'
constructor() {
// without referencing this.field before super(), this.field stays undefiend
this.field
super()
}
}
new Child() #=> 'child'
Is there any ways to accomplish the following conditions?
omit the whole Child's constructor declaration like the first example
grab the member variable in Child class?
What jumps to mind is:
class Parent {
constructor(public field: string) {
alert(this.field)
}
}
class Child extends Parent {
constructor() {
super('child');
}
}
new Child() #=> 'child'
This doesn't meet your conditions but I feel it is fairly compact.
Well you could defer the property access to a micortask:
class Parent {
field: string
constructor() {
Promise.resolve().then(() => {
alert(this.field)
};
}
}
But while that fullfills your conditions, it is ... still the wrong approach. Pass field as a constructor argument, as other answers show.
There's no way to accomplish your conditions, i'm pretty sure.
Grabbing the member variable in sub class happens after the base class constructor runs, and calling super() must be the first statement in a sub class constructor.
class Child extends Parent {
field = 'child';
}
// the above is equal to:
class Child extends Parent {
constructor(){ super(); this.field = 'child'; }
}
And this would cause error:
class Child extends Parent {
constructor(){
this.field = 'child'; // ERROR!
super();
}
}

Angular bind ViewChild to Property in Class

I'm trying to figure out how to bind a view child to a child component of a class inside of my view.
I have a models that emulates binary expression:
export interface IODataExpression{
}
export class ODataExpressionDescriptor implements IODataExpression{
property: ODataProperty;
selectedFunction: ODataFunctionDescriptor;
value: any;
isNegated: boolean = false;
}
export class ODataBinaryExpressionDescriptor implements IODataExpression{
left: IODataExpression;
right: IODataExpression;
operator: ODataBinaryOperators;
}
I have a component class which looks like so:
binaryExpression: ODataBinaryExpressionDescriptor = new ODataBinaryExpressionDescriptor();
binaryOperatorKeys: any;
binaryOperators = ODataBinaryOperators;
#ViewChild('left') leftExpression: OdataSimpleFilterComponent;
the left property points to a component which internally has a property:
odataExpression: ODataExpressionDescriptor = new ODataExpressionDescriptor();
How can I make it so that the binaryExpression.left always equals the view childs leftExpression.odataExpression?
Use an EventEmitter.
In OdataSimpleFilterComponent
#Output() odataExpressionChange = new EventEmitter<ODataExpressionDescriptor>();
Then, whenever tha value changes internally in the component, you do:
this.odataExpressionChange.emit(this.odataExpression);
In the main component, you'll have to do in ngAfterViewInit (or ngAfterViewChecked), to make sure that leftExpression is initialised:
ngAfterViewInit() {
leftExpression.odataExpressionChange.subscribe(data => {
this.binaryExpression.left = data;
}
}
This way, whenever the value changes in the child component, you'll receive a notification (via the subsrcription to the EventEmitter) and can react accordingly.
Of course some details might change, as I can't know all of the details of your implementation.

Javascript inheritance - how to check class type?

I have implemented inheritance in javascript like this:
Parent class:
class Parent {
constructor(data) {
super(data);
...
}
}
export default Parent;
and children classes:
ChildA
class ChildA extends Parent {
constructor(data) {
super(data);
...
}
}
export default ChildA;
and ChildB:
class ChildB extends Parent {
constructor(data) {
super(data);
...
}
}
export default ChildB;
Now I got from server object which is mapped to one of these children base on flag. This flag is not in objects, so is possible how to later in code what of type is my object?
I tried myObj.constructor.name == 'ChildA' and myObj.constructor.name == 'ChildB' but it always returns false.
The simplest solution would be to have a type property on your classes that tells what kind of class each one is. It makes checking very simple.
A more involved solution would be to use Typescript, which has inheritance and typeguards built in.

Accessing base member from derived class in function

I have created Angular2 + Typescript project. I have there alot of tables so I want to have something like base component for that.
There is my base component:
export abstract class ManagementComponent<T> implements BaseComponent {
protected selectedItem: T;
protected items: Array<T>;
}
Now there is my child component. I would like to get all items from http and then assign it into base class
export class CompetencesComponent extends ManagementComponent<Competence> implements OnInit {
thisField: string;
constructor(private service: CompetencesService) {
super();
}
ngOnInit(): void {
this.getCompetences();
}
private getCompetences() {
this.service.getCompetences().subscribe(function (competences: Array<Competence>) {
this.thisField // ok
this.items // not ok
})
}
}
Any idea how I can access base fields from subscribe methods?
Currently I'd expect that you wouldn't be able to reference either thisField or items, because you should be losing the this context inside your subscription function.
You can switch to an arrow function to retain context:
this.service.getCompetences().subscribe((competences: Array<Competence>) => { ... }
You can set list of competencies to parent class as follow:
private getCompetences() {
var self = this;
this.service.getCompetences().subscribe(function (competences: Array<Competence>) {
this.thisField // ok
self.items = competences; // not ok
})
}
The reason you are unable to access items property through this binding is the scope. Inside callback this binding is bound to something else and you loose the context.

spying on/mocking super class methods in es6

The below are examples but get at the gist of my problem ...
super class:
class Parent {
constructor(a) {
this._a = a;
}
doSomething() { ... implementation... }
}
child-class:
class Child extends Parent {
constructor() {
super('a');
}
doSomethingElse() { return super.doSomething(); }
}
I am using these classes in Angular, so the Parent class is DI'ed into the factory which provides the Child class, something like this:
function ChildDeps(Parent) {
return class Child extends Parent {
... Child class implementation here ...
};
}
ChildDeps.$inject = ['Parent']
Naively, I first tried something like this inside a provide before each clause:
beforeEach(module($provide => {
parent = {
doSomething: jasmine.createSpy('parent.doSomething')
};
Parent = jasmine.createSpy('Parent').and.returnValue(parent);
$provide.value('Parent', Parent);
}));
But this did not work ... saying that spy 'Parent' was never called.
Currently using jasmine/karma for testing. How can mock/spy the super class so I can make expectations about what the Parent class' constructor is called with and that the super.doSomething function is called?
Thanks!

Categories

Resources