I'm building an app with webpack for the first time and i'm trying to wrap my head around organizing class files. I'm having trouble getting the code to work. I'm still new to ES6 and such, so my code below is probably very wrong but i'm not sure its my approach/concept or its my syntax.
entry is index.js and I also have these files
import App from './js/app.js';
import User from './js/user.js';
import Guest from './js/guest.js';
const app = new App();
const user = new User();
const guest = new Guest();
$(document).ready(function () {
app.DatabaseStore.senddata();
console.log( user.getall() );
});
src/js/app.js the main global method/variable class
import CookieStore from './cookie.js';
import DatabaseStore from './database.js';
export default class App {
constructor() {
this.cookieStore = new CookieStore();
this.databaseStore = new DatabaseStore();
}
gettime() {
return 'time';
}
}
src/js/user.js methods that are for users
import App from './app.js';
export default class User extends App {
constructor() {
this.mydata = App.cookieStore.getData();
console.log(this.mydata );
}
getall() {
return ['foo', 'bar', 'baz'];
}
}
src/js/guest.js methods that are for guests
import App from './app.js';
export default class Guest extends App {
constructor() {
this.mydata = App.cookieStore.getData();
}
}
src/js/cookie.js cookie manipulating methods
export default class CookieStore {
constructor() {}
mydata() {return 'foo';}
}
src/js/database.js firebase methods
export default class DatabaseStore {
constructor() {}
senddata() {
this.mydata = App.cookieStore.getData();
}
You are trying to access instance property statically. You need to create an instance of App class before trying to access cookieStore property. You can create an instance and export it in your app.js to have singleton instance.
//in your app.js
export const app = new App();
in other files
import {app} from './js/app.js'
app.cookieStore.getData();
Related
I write UI tests using PageObject Pattern (NodeJS + Webdriverio) and I have a base class (BasePage), a page class(MyPage), a popup component class(PopupComponentClass) with multipurpose behaviour, a popup class with a specific implementation(SpecificPopupComponentClass). I need to extend SpecificPopupComponentClass from PopupComponentClass.
page.js:
export default class BasePage {
get BASE_URL() {
return "https://url.com";
};
...some methods...
}
my.page.js:
import BasePage from "../page";
class MyPage extends BasePage {
constructor() {
super();
};
get URL() { return `${this.BASE_URL}/some/path` };
get title() { return $("h1") };
orderRandomTariff() {
...some actions...
};
}
export default new MyPage ();
popup.component.page.js:
import BasePage from "../pages/page";
class PopupComponent extends BasePage{
constructor() {
super();
};
get title() { return $("h1") };
}
export default new PopupComponent();
specific.popup.component.js:
import PopupComponent from "./popupFragment";
class SpecificPopupComponent extends PopupComponent {
constructor() {
super();
};
get popupStreetInput() { return $(".//div[#class='checkAddress']//*[./*[contains(text(),'Street')]]//input") };
fillStreet(street) {
...some actions with this.popupStreetInput...
};
}
export default new SpecificPopupComponent();
...and trying to use it in test.js:
import MyPage from "../../../../pages/my.page";
import SpecificPopupComponent from "../../../../fragments/specific.popup.component";
const myPage= MyPage ;
const popup = SpecificPopupComponent ;
describe("Test", () => {
before(() => {
myPage.open();
});
it("Check", () => {
popup.fillStreet("Street");
});
});
but I'm getting an error: "TypeError: Class extends vlaue #PopupComponent is not a constructor or null".
I suspect this is due to circular dependencies, but I can't understand, what I need to do to fix that.
It seems the issue here is how you're exporting the base class. You're instantiating it instead of just exporting the class you'll inherit from. It should be like this:
export default class PopupComponent extends BasePage {
constructor() {
super();
};
get title() { return $("h1") };
}
And then create the instance when you're going to use it
var myPage = new MyPage()
var popup = new SpecificPopupComponent()
myPage.open()
popup.fillStreet('street')
What you're doing there is equivalent to doing this:
class SpecificPopupComponent extends new PopupComponent() {
// ... what am I? 🤔
}
I suspect this is due to circular dependencies
You can validate or reject your suspects by copying all the code into the test file in the correct order without using imports. But I don't think it's an circular dependency
I created this Plunker to remove the usage of imports and prove this.
I am currently trying to implement a mobx storage which I can call from everywhere like so:
import {userStore} from '../UserStore.js';
At the end of the file, my export functionality looks as follows:
const userStore = new UserStore();
export {userStore};
As I understand, everytime I call the import functionality, the object gets re-created with which multiple files that import UserStore don't share the same variables.
However, I want that every file that imports UserStore imports the same object with the exact same variables. How can I achieve this? I am not fully sure how to achieve, so any ideas and examples would be appreciated :)
The full code (for the UserStore.js declaration), if of any help, is as follows (look at the very bottom for the export statement)
import {observable, computed, action} from 'mobx';
import {ObservableMap, toJS} from 'mobx';
import {Fb} from './firebase.js';
class UserStore {
/** GPS */
#observable usrLng = 0.0;
#observable usrLat = 0.0;
#observable watchID = null;
#action
watchCurLocation() {
this.watchID = navigator.geolocation.watchPosition((position) => {
console.log("Recording GPS data from within the Store!!");
this.usrLat = parseFloat(position.coords.latitude);
this.usrLng = parseFloat(position.coords.longitude);
}, (error) => console.log(JSON.stringify(error)), {
enableHighAccuracy: true,
timeout: 2000,
maximumAge: 1000
});
}
#action
clearWatch() {
navigator.geolocation.clearWatch(this.watchID);
}
/*/ GPS */
/** BIKE BOOKING */
#observable interestBikeNo = -1;
#observable bookedBikeNo = -1;
#action
setInterestBikeNo(bn) {
this.interestBikeNo = bn;
}
}
const userStore = new UserStore();
export {userStore};
You simply need a singleton instance of UserStore class
Sample demo
let localInstance = null;
export class Apple {
static newInstance() {
if (! localInstance)
localInstance = new Apple();
return localInstance;
}
}
// usage
import {Apple} from './apple';
const instance = Apple. newInstance();
In your case, you can use a simple function
import {observable, computed, action} from 'mobx';
import {ObservableMap, toJS} from 'mobx';
import {Fb} from './firebase.js';
class UserStore {
// omitted
}
let userStore;
export function getUserstore() {
if (!userStore)
userStore = new UserStore();
return userStore;
};
Somewhere in code
// instead of
import {userStore} from './someUserStoreModule';
// use
import {getUserstore} from './someUserStoreModule';
const userStore = getUserstore();
Using JavaScript ES6 I have several classes into which I want to separate the various concerns of my app. I have a main.js file in which I wish to instantiate the classes and then be able to reference and call methods across them.
My question is: What is the best/standard way to do this? My current approach is as follows;
In main.js I create an App class which instantiates two classes
import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';
export default class App {
constructor () {
this.one = new ClassOne(this);
this.two = new ClassTwo(this);
}
}
const app = new App();
Then in ClassOne.js I do something like this
export default class ClassOne {
constructor (app) {
this.app = app;
this.app.two.callMethod();
}
}
It certainly works, but does it look stoopid & is there a better way of doing it?
I would suggest having a setter in ClassOne and ClassTwo. That way only ClassOne and ClassTwo are dependent on each other, and not on an instance of App.
ClassOne.js
export default class ClassOne {
setTwo (two) {
this.two = two;
this.two.callMethod();
}
}
ClassTwo.js
export default class ClassTwo {
setOne (one) {
this.one = one;
this.one.callMethod();
}
}
main.js
import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';
export default class App {
constructor () {
this.one = new ClassOne();
this.two = new ClassTwo();
this.one.setTwo(this.two);
this.two.setOne(this.one);
}
}
const app = new App();
I'm building an Aurelia app that uses "Models" for every type of data object.
All my Models look something like this:
export class Item {
id = null;
name = '';
description = '';
constructor (data) {
Object.assign(this, data);
}
}
And I later create objects like this:
export class SomeViewModel {
activate () {
this.myItem = new Item({
name: 'My Item!',
description: 'This is my item. It will be initialized with these properties.'
});
}
}
I got the Object.assign() bit from an article I read and it works really well. It allows me to create new items using data from the server, or if I want an empty Item I simply don't pass in anything.
Now I've reached a point where I need my model to have access to another class so I'm using Aurelia's Dependency Injection like this:
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class Item {
id = null;
name = '';
description = '';
constructor (router, data) {
this.router = router;
Object.assign(this, data);
}
get permalink () {
return window.location.protocol + '//' + window.location.host + this.router.generate('item', {itemId: this.id});
}
}
Now my problem is this; how do I create a new Item() without passing in the Router myself? I guess switching the order of argument to constructor() would do the trick but that doesn't seem to work with Aurelia?
And I don't want to have to do this every time I create a new Item:
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class SomeViewModel {
constructor (router) {
this.router = router;
}
activate () {
this.myItem = new Item(this.router, {
name: 'My Item!',
description: 'This is my item. It will be initialized with these properties.'
});
}
}
Surely there must be a better way to solve this?
Use the Factory resolver. Here's an example: https://gist.run?id=46642ac54893186067e7cd890d6722a3**
import {inject, Factory} from 'aurelia-dependency-injection';
import {MyModel} from './my-model';
#inject(Factory.of(MyModel))
export class App {
message = 'Hello World!';
constructor(createModel) {
let model = createModel('my data');
}
}
my-model.js
import {inject} from 'aurelia-dependency-injection';
import {EventAggregator} from 'aurelia-event-aggregator';
#inject(EventAggregator)
export class MyModel {
constructor(eventAggregator, data) {
console.log(eventAggregator, data);
}
}
I m actually learning typescript, and I m facing some problems with internal modules.
In fact, I have three files :
index.ts in which I start my app
///<reference path='RouteManager.ts'/>
import RouteManager = RestifyRouting.RouteManager;
var myManager = new RouteManager();
myManager.init("superpath");
RouteManager.ts that manage my REST routes
///<reference path='RouteParser.ts'/>
module RestifyRouting {
export class RouteManager {
routeParser:RouteParser;
constructor() {
}
public init(filePath) {
this.routeParser = new RouteParser();
this.routeParser.register("zfaf","callback");
console.log(filePath);
}
}
}
RouteParser which has to parse some string to get some informations
module RestifyRouting {
export class RouteParser {
constructor() {
}
public register(path, callback) {
console.log('super register');
}
}
}
I have a gulp file that creates my .js and d.ts files and it works great, except for the index.js file. The compiler tells my that RestifyRouting (which is my internal module) is undefined and I dont know why...
Can you help me ?
PS : every files are in the same folder, it's just a learning application.
Thanks for advance
As of TypeScript 1.5 the module syntax is aligned with ES6 module syntax and that is what I have been using as well...
You can remove any references to TypeScript modules and just export the classes directly
index.ts
import { RouteManager } from './RouteManager';
var myManager = new RouteManager();
myManager.init("superpath");
RouteManager.ts
import { RouteParser } from './RouteParser';
export class RouteManager {
routeParser:RouteParser;
constructor() {}
public init(filePath) {
this.routeParser = new RouteParser();
this.routeParser.register("zfaf","callback");
console.log(filePath);
}
}
RouteParser.ts
export class RouteParser {
constructor() {}
public register(path, callback) {
console.log('super register');
}
}
Keeping modules
If you'd like to keep using internal modules then you have to be sure to export your module as well as the classes inside the module.
// RouteManager.ts
export module RestifyRouting {
export class RouteManager{}
}
//index.ts
import { RestifyRouting } from './RouteManager';
//usage
var manager = new RestifyRouting.RouteManager();
Something to keep in mind is that you will not be able to import multiple items into the the same name.
// i.e.
import { RestifyRouting } from './RouteManager';
import { RestifyRouting } from './RouteParser';
NOTES
the {} syntax in the import statement can allow multiple imports
{ Class1, Class2 }
The {} can be skipped if you exporting a default:
//Source (foo.ts):
export default class Foo{}
//Reference:
import Foo from './foo';
//usage:
class User {
foo: Foo;
}