ES6 import issue - javascript

I am creating a Single page application base on MVC, and I am stuck with a small issue. I am exporting the reference of controller class and I am importing it at a few places and it is working fine but when I am trying to import it into a specific file, it's not working, I spent a lot of time, but couldn't figure it out. I am sure I am missing some obvious thing. Here is my code(Link to Repo for more details):
Controller(Actual File):
class Controller extends Base {
constructor(){
super()
//more code
}
//more code
static create() {
return new Controller() // planning to make a singleton later on
}
}
const controller = Controller.create()
export default controller
Model(import works in this one, Actual file):
import controller from '$js/Controller'
export default class Model {
... Model code
static fxn(){
controller.controllerFunction()
}
}
Utils File(import doesn't work in this file, Actual File):
import controller from '$js/Controller'
export function someFunction(args) {
const value = controller.get() // Throws an error saying `controller` is not defined
}
Here is the Github Repo link. Please let me know if you need anything else.

Related

Is there a way to execute code from a ES6 class file before it is even referenced it?

I'm not an expert on JS and I have inherited a React app with dozens and dozens of components.
I want to do something that in Java is trivial but I can't find the way in ES6.
I want to build a registry of most of those components and I'm looking for an approach to have each class register itself so it can be looked up dynamically by a key.
So I build a registry class like this
let registry = [];
export default class Registry {
static register(component) {
if (!registry.find(x => x.key == component.key))
registry.push(component);
}
}
And on each component class, I tried to register itself doing something like this:
import Registry from './Registry.jsx';
import React from 'react';
export default class Component extends React.Component {
... body of the component ...
}
Registry.register( { key: 'ComponentX', component: Component });
But it doesn't work because Registry is undefined.
In Java would be something like:
class Component {
....
static {
Registry.register('ComponentX',Component.class);
}
....
}
The only alternative I found is to create a static list of all components but that chokes with our current distributed approach to development
Thanks a lot
Edit
Thanks guys. I'd managed to get a step closer to the solution.
Using this:
let registry = new Map();
export function register(key, component) {
return registry.set(key, component);
}
import { register } from './Registry.jsx';
export default class Component extends React.Component {
static entry = register(key, component);
... body of the class ...
}
Using this scheme, the register function is invoked but the registry variable is undefined. I just need to find out how to have it defined at the time of the invocation of the register function.

Scope import for an instance only

Good evening to everyone.
I'm not sure how can I explain my issue. I will show it to you by showing examples of the code and expected results. I could not use code from the real issue because the code is under license. I am very sorry for that and I will be glad of someone can help me solve my issue.
I'm using latest version of webpack, babel.
My application is spliced to three parts what are dynamically imported by each other. It is mean if I run split chunks plugin it will really create three clear files.
The parts are Core, Shared, Application. Where the Core only creating an instance of the application.
Result of the parts is bundled to single file. So it is linked by one html's script tag.
Project structure is:
src/app // For Application
src/core // For Core
src/shared // For Shared
In webpack configuration I am resolving alias for import ˙Editor$˙.
I renamed naming of variables because they are including project name.
resolve: {
alias: {
"Editor$": path.resolve('./src/app/statics/Editor.js'),
}
},
The content of Core file is
function createInstance(name, id) {
import("app").then(App => {
App(name, id)
});
}
The little bit of Application file is
imports...
import Framework from "./framework"
function createApp(name, id) {
new Framework({name, id}).$mount(...)
}
export default createApp
In the Application classes (what are instantiated inside Framework)
Is this import
import Editor from "Editor"
The Editor class is a singleton. But only for created instance.
class Editor {
static instance;
id = null;
constructor(){
if(this.constructor.instance){
return this.constructor.instance
}
this.constructor.instance = this
}
static get Instance() {
return this.instance || (this.instance = new this())
}
static get Id {
return this.Instance.id;
}
}
export default Editor
The issue is webpack dependency resolving. Because webpack puts and unify all imports to the top of the file.
So the imports are evaluated once through the life-cycle of the program.
But I need to tell webpack something like: There is an instance creation. Declare the new Editor singleton for this scope. Don not use the already cached one.
My another idea how to fix this is to set context for the instance. And in the Editor singleton create something like new Map<Context, Editor> if you get what I mean. But I did not find a way how to set a context for an instance or scope the import only for it.
I will appreciate any help. I am googling two days and still no have idea how to do it without rewriting all the imports.
Sorry for bugs in my English. I am not native speaker and my brain is not for languages.
Thanks everyone who take look into my issue.
How about recreating the Editor:
// Editor.js
class Editor {
// ...
}
let instance;
export function scope(cb) {
instance = new Editor();
cb();
instance = null;
}
export default function createEditor() {
if(!instance) throw Error("Editor created out of scope!");
return instance;
}
That way you can easily set up different scopes:
// index.js
import {scope} from "./editor";
scope(() => {
require("A");
require("B");
});
scope(() => {
require("C");
});
// A
import Editor from "./editor";
(new Editor()).sth = 1;
// B
import Editor from "./editor";
console.log((new Editor()).sth); // 1
// C
import Editor from "./editor";
console.log((new Editor()).sth); // undefined
// note that this will fail:
setTimeout(() => {
new Editor(); // error: Editor created out of scope
}, 0);
That also works for nested requires and imports as long as they are not dynamic.

import or require React components dynamically

I'm trying to import / require components dynamically, but somehow when I do it React complains. The require function does find it, but React throws an error saying it is missing some functions 't' etc.. All of this in an electron app.
I have a wizard setup (that is working, but not so elegant I think), where each page has it's own layout and jsx component. If I'd like to add a new page, I don't want to manage x-number of files, and at the moment I have to due to the setup I have currently. Below you can find what I want to achieve and what I'm doing now to achieve it. If there are any suggestions, code smells or better options please let me know as I'm quite new to React and ES2015 (as I'm from a C# background).
What I'm trying to achieve
export default class WizardPageContainer extends Component {
// Constructor
constructor(props) {
super(props);
}
// Render
render() {
const WizardPage = require(`./path/to/${this.props.step.id}`);
return (
<WizardPage step={this.props.step} />
);
}
}
How I'm currently doing it : which means I have to declare the imports / files first on top of the "WizardPageContainer" component.. Which means extra work and prone to errors/forgetting things. I should add, this code is working now ok, but I don't think this is elegant/future proof:
/* PAGES */
import WizardPage_Welcome from './pages/0.wizard.welcome';
import WizardPage_SystemCheck from './pages/1.wizard.systemCheck';
import WizardPage_SignIn from './pages/2.wizard.signIn';
import WizardPage_ExamCode from './pages/3.wizard.examCode';
import WizardPage_TakeExamination from './pages/4.wizard.takeExamination';
import WizardPage_Close from './pages/5.wizard.close';
const pages = [
WizardPage_Welcome,
WizardPage_SystemCheck,
WizardPage_SignIn,
WizardPage_ExamCode,
WizardPage_TakeExamination,
WizardPage_Close
];
/*/********************************************************************///
/* ******************************************************************** */
/* COMPONENT */
export default class WizardPageContainer extends Component {
// Constructor
constructor(props) {
super(props);
}
// Render
render() {
const WizardPage = pages[`${this.props.step.id}`];
return (
<WizardPage step={this.props.step} />
);
}
}
/*/********************************************************************///
I think it is about the "default". i have problem like this. Can you check this code;
https://github.com/robeio/robe-react-admin/blob/master/src/app/HasAuthorization.jsx#L10
Also you can check the example usage;
https://github.com/robeio/robe-react-admin/blob/master/src/app/HasAuthorization.jsx#L26
Your const pages needs to be an object, not an array.
You can see a working version I made of this here:
https://github.com/Frazer/meteor-react-nav/blob/master/lib/jsx/App.jsx
Best advice: Use Webpack to handle your imports, it's way more efficient than we could ever be.

How to include external JavaScript libraries in Angular 2?

I am trying to include an external JS library in my Angular 2 app and trying to make all the methods in that JS file as a service in Angular 2 app.
For eg: lets say my JS file contains.
var hello = {
helloworld : function(){
console.log('helloworld');
},
gmorning : function(){
console.log('good morning');
}
}
So I am trying to use this JS file and reuse all the methods in this object and add it to a service, so that my service has public methods, which in turn calls this JS methods. I am trying to reuse the code, without reimplementing all the methods in my typescript based Angular 2 app. I am dependent on an external library, which I cant modify.
Please help, thank you in advance.
With ES6, you could export your variable:
export var hello = {
(...)
};
and import it like this into another module:
import {hello} from './hello-module';
assuming that the first module is located into the hello-module.js file and in the same folder than the second one. It's not necessary to have them in the same folder (you can do something like that: import {hello} from '../folder/hello-module';). What is important is that the folder is correctly handled by SystemJS (for example with the configuration in the packages block).
When using external libs which are loaded into the browser externally (e.g. by the index.html) you just need to say your services/component that it is defined via "declare" and then just use it. For example I recently used socket.io in my angular2 component:
import { Component, Input, Observable, AfterContentInit } from angular2/angular2';
import { Http } from 'angular2/http';
//needed to use socket.io! io is globally known by the browser!
declare var io:any;
#Component({
selector: 'my-weather-cmp',
template: `...`
})
export class WeatherComp implements AfterContentInit{
//the socket.io connection
public weather:any;
//the temperature stream as Observable
public temperature:Observable<number>;
//#Input() isn't set yet
constructor(public http: Http) {
const BASE_URL = 'ws://'+location.hostname+':'+location.port;
this.weather = io(BASE_URL+'/weather');
//log any messages from the message event of socket.io
this.weather.on('message', (data:any) =>{
console.log(data);
});
}
//#Input() is set now!
ngAfterContentInit():void {
//add Observable
this.temperature = Observable.fromEvent(this.weather, this.city);
}
}

how to use auto generated typescript declaration files in separate project?

I have developed typescript library which consists of several classes located in separate ts files.
app.ts
//imported class from separate file
import leafAdd = require('./Base/leaf');
export class MyClass {
public leafInstance : leafAdd.Leaf;
}
var MyClassInstance = new MyClass();
The code works fine so i want to use my library in a new separate project, still I do not want to transfer whole code. Instead I just want to use definition files from typescript compiler (generated by adding --declarations flag). The declaration files look like this:
app.d.ts
import leafAdd = require('./Base/leaf');
export declare class MyClass {
public leafInstance : leafAdd.Leaf;
}
When I try to reference this file in a new project it somehow does not work:
newapp.ts
/// <reference path="./typings/app.d.ts" />
export class MyOtherClass{
public myClass: MyClass; //Compiler error: Could not find symbol MyClass
constructor() {
//some other code
}
}
And I got compiler error saying: "Could not find symbol MyClass"
Perhaps I am missing something obvious or just trying to reference the code in a wrong way. I would be really gratefull if someone can point me to the right direction.
Ok I got it. I should have looked at app.d.ts file for solution :). Simply, it seems that declaration files containing
export declare class ...
can not be referenced using
/// <reference path="./path/to/declaration.d.ts" />
and should be imported like any other module/class. So working code looks like this:
import myclMod = require('./typings/app') //please notice missing file extension - it confused me at the beginning :)
export class MyOtherClass{
public myClass: myclMod.MyClass;
constructor() {
//some other code
}
}

Categories

Resources