Inheritance with Aurelia - javascript

Hi I am using Aurelia with Visual studio 2015.
I am creating a sports data related site.
Here I am having a base class which fetches basic details regarding the sports event. I inherit this base class from another class and fetch more information based on the base class property value.
Here is my base class --
import {inject} from 'aurelia-framework';
import {SportsEventService} from '../services/data-services/sports-event-service.js';
#inject(SportsEventService)
export class BaseClass{
sportsEvent;
constructor(sportsEventService){
this.SportsEventService = sportsEventService;
}
getSportsEventDetail(sportsEventName){
return this.SportsEventService.getSportsEventDetail(sportsEventName)
.then(response => {
this.sportsEvent = response;
return this.sportsEvent;
});
}
}
Here is my child class which inherits base class -
import {inject} from 'aurelia-framework';
import {SportsEventService} from '../services/data-services/sports-event-service.js';
import {SportsEvent} from './sports-event'
#inject(SportsEventService)
export class ChildClass extends BaseClass{
constructor(sportsEventService){
super(sportsEventService);
}
getUpcomingFixture(){
return (this.UpcomingFixtureService.getUpcomingFixture(this.sportsEvent.leagueId)
.then(response => {
return response;
}));
}
}
Here, when I am using baseClass property, "this.sportsEvent" it is giving me "Undefine".
Can anybody tell me, how can I make this work?

this.sportsEvent will be undefined until it's assigned at the this.sportsEvent = response; line.
You won't be able to call the ChildClass.getUpcomingFixture method until the base class's getSportsEventDetail method has finished because ChildClass.getUpcomingFixture depends on this.sportsEvent.
Try executing the code like this:
childClass.getSportsEventDetail(sportsEventName)
.then(() => childClass.getUpcomingFixture());

Related

Why would you need to null coalesce a static member initialization?

I'm looking through the Mixpanel for React Native example project and they're initializing a singleton like this:
import {Mixpanel} from 'mixpanel-react-native';
import {token as MixpanelToken} from './app.json';
export default class MixpanelManager {
static sharedInstance = MixpanelManager.sharedInstance || new MixpanelManager();
constructor() {
this.configMixpanel();
}
configMixpanel = async () => {
this.mixpanel = await Mixpanel.init(MixpanelToken);
}
}
I've never seen a singleton handled quite this way. What's the circumstance where MixpanelManager.sharedInstance will already be set when this class gets declared?

Using static in page object (Cypress)

Looking through various examples of implementing e2e tests on Cypress, I came across the fact that many people use the method of creating a new object, instead of using static. Why do they do this? Why not use static for page-object methods, because we don't change any data in the class itself and, accordingly, don't communicate to this, and we don't need to have multiple instances of the same page (or I don't see a scenario for using this). I understand that Selenium uses page factory and because of this it is necessary to create a new object, but I did not find an analogy in Cypress.
Example of creating a new object:
import { BasePage } from './BasePageClass'
import { navMenu } from './NavigationMenuClass';
import { queryPage } from './QueryPageClass';
export class MainPage extends BasePage {
constructor() {
super();
this.mainElement = 'body > .banner';
}
verifyElements() {
super.verifyElements();
cy.get(this.mainElement).find('.container h1').should('be.visible');
}
switchToQueryingPage() {
navMenu.switchToQueryingPage();
queryPage.verifyElements();
}
};
export const mainPage = new MainPage();
Example using static:
import { BasePage } from './BasePageClass'
import { navMenu } from './NavigationMenuClass';
import { queryPage } from './QueryPageClass';
export default class MainPage extends BasePage {
static mainElement = 'body > .banner';
constructor() {
super();
}
static verifyElements() {
super.verifyElements();
cy.get(MainPage.mainElement).find('.container h1').should('be.visible');
}
static switchToQueryingPage() {
navMenu.switchToQueryingPage();
queryPage.verifyElements();
}
};
Here is an example of a composition of commands my seniors have taught me to use. I have a function buyProduct, but it requires several steps and I have made them in different commands that can be used in different cases:
it('buyProductAsCustomer', ()=>{
cy.login(customer)
cy.shopFe_openProductByName(product.name)
cy.shopFe_addProductToCart()
cy.shopFe_openCheckoutFromCart()
cy.shopFe_selectPaymentMethod("payWithCreditCardMethod")
cy.shopFe_fillCheckoutFormAsCustomer(customer)
cy.shopFe_checkoutPageGetOrderData()
cy.shopFe_submitCheckoutForm()
cy.shopFe_completePaymentWithCreditCard()
});
it('buyProductAsGuest', ()=>{
cy.shopFe_openProductByName(product.name)
cy.shopFe_addProductToCart()
cy.shopFe_openCheckoutFromCart()
cy.shopFe_selectPaymentMethod("payWithCashMethod")
cy.shopFe_fillCheckoutFormAsGuest(guest)
cy.shopFe_checkoutPageGetOrderData()
cy.shopFe_submitCheckoutForm()
cy.shopFe_completePaymentWithCreditCard()
});
These 2 cases can be done in command with several variables, but in time those variables tend to increase tenfold. Thus we separate them into smaller repeatable parts that can be combined in different ways.

Hacking the import statement to extend an inherited class

In a library that I wish to extend without modifying its code, several classes inherit from the same imported one. That is in this BaseClass I would need to overwrite a specific method.
In the library (written in TypeScript) :
import { BaseClass } from './base_class';
export class ClassA extends BaseClass {}
import { BaseClass } from './base_class';
export class ClassB extends BaseClass {}
…
In the external extension I wish to write :
import { BaseClass } from 'library';
export class ExtendedBaseClass extends BaseClass {
oneMethod() {
const data = BaseClass.prototype.oneMethod.call(this);
// make additional things with data
return data;
}
}
Is there a way for this new ExtendedBaseClass to become the parent of all ClassXs ? At least in a new extended and re-exported version of them without the need to copy their internal code.
Is there a way for this new ExtendedBaseClass to become the parent of all ClassXs?
No.
An alternative might be to replace the one method directly on the base class:
import { BaseClass } from 'library';
const oneMethod = BaseClass.prototype.oneMethod;
Object.defineProperty(BaseClass.prototype, 'oneMethod', {
value() {
const data = oneMethod.call(this);
// make additional things with data
return data;
},
});
There's no way to do exactly what you're asking, but you could achieve the same result by extending each class individually.
ExtendedClassA extends ClassA {
oneMethod() {
// call a shared method if you need to reuse
}
}
// ExtendedClassB, etc

Use JavaScript class in TypeScript

I have a problem introducing TypeScript to our JavaScript project.
First I want to use TypeScript only in my part of the code, leaving the JavaScript untouched.
Now I try to use a JavaScript class in my TypeScript code, but I don't find a solution in the last days.
The head of my TypeScript class with import of the JavaScript:
import { BaseLogic } from "../baseLogic";
export class ClaimLogic extends BaseLogic {
...
The JavaScript class ("baseLogic.js"):
module.exports = class BaseLogic {
constructor(meta, logger) {
...
My *.d.ts file ("baseLogic.d.ts"):
export class BaseLogic {
meta: any;
log: any;
constructor(meta: any, logger: any)
}
The head of the compiled JavaScript:
const baseLogic_1 = require("../baseLogic");
class ClaimLogic extends baseLogic_1.BaseLogic {
...
As you see in the compiled JavaScript baseLogic_1.BaseLogic is used.
This results in following error:
TypeError: Class extends value undefined is not a constructor or null
With only baseLogic_1 after the extends keyword in the JavaScript file all is fine.
I have no idea about a solution and hope you can help me!
Your import suppose to be import * as BaseLogic from "../baseLogic";.
In that way you will get the Class that you put on module.exports.
The codesnipet in baseLogic.js exports the class.
module.exports = class BaseLogic {
constructor(meta, logger) {
...
}
You try to access with class ClaimLogic extends baseLogic_1.BaseLogic an object that includes the class BaseLogic
Solution
import BaseLogic from '../baseLogic'
// or: const BaseLogic = require("../baseLogic");
class ClaimLogic extends BaseLogic {
...
}

Node.js v6.2.0 class extends is not a function error?

So I'm trying to extend a class in node js and the compiler keeps returning the following error:
TypeError: Class extends value #<Object> is not a function or null
I checked that I was exporting the class correctly and I am, any ideas? I'll post my code below:
/handler/venue.js:
var VenueViews = require('../views/venue'); // If I remove this the error will dissapear (as expected)
class Venue {
constructor(data) {
this.setDataHere = data;
}
main () {
var View = new VenueViews(); // This doesn't run
}
}
module.exports = Venue;
/views/venue.js:
var Venue = require('../handlers/venue');
console.log (Venue) // This returns {} ???
class VenueViews extends Venue {
constructor() {
super();
}
}
module.exports = VenueViews;
I know that node supports these es6 features, so I'm unsure why they aren't working?
Edit:
I'm not sure if this is suppose to happen but, when I log my Venue require it returns an empty object {}.
console.log (Venue) // This returns {} ???
So it turns out I had a circular reference in my code, where I was importing the class that was extending, into the class that itself was extending (tongue twister :P).
The obvious fix was to simply remove the extends reference and find another way of doing what I was trying to achieve. In my case it was passing the Venue class properties down into the VenueViews constructor.
E.g var x = VenueViews(this)
In my instance, it was the same issue as #James111 was experiencing (circular import) due to a factory pattern I was trying to set up in Typescript. My fix was to do move the code into files, similar to the following:
// ./src/interface.ts
import { ConcreteClass } from './concrete';
export interface BaseInterface {
someFunction(): any;
}
export class Factory {
static build(): BaseInterface {
return new ConcreteClass();
}
}
// ./src/base.ts
import { BaseInterface } from './interface';
class BaseClass implements BaseInterface {
someFunction(): any {
return true;
}
}
// ./src/concrete.ts
import { BaseClass } from './base';
export class ConcreteClass extends BaseClass {
someFunction(): any {
return false;
}
}
I had faced similar issue, after checking all the workaround finally issue got resolved by deleting the node_modules folder and run npm i.

Categories