Im getting the following error when doing this.
Super expression must either be null or a function, not undefined
What I'm trying to do in javascript which I can do in c# is have the child class be able to call the parent class and use functions that instantiate the base class again. Say for instance you have a navbar on a page and each icon takes you to a different page but the navbar is always visible. By inheriting from the parent page I would be able to keep the code dry like we do in c# but for some reason javascript is flipping out when trying to do the same thing even if I just pass null into the super.
Doing this would allow me to havenew Support(browser).someMethod().cb().someMethod()
import { Support } from "./community/Support";
export class NavigationController {
constructor(browser){
this.browser = browser;
}
cb(){
this.browser.cool()
return new Support(this.browser);
}
import { NavigationController } from "../navigation_controller";
export class Support extends NavigationController {
constructor(browser){
super(browser);
this.browser = browser;
}
someMethod(){
this.browser.blah()
return this;
}
Related
How to avoid circular references at the same time create some child classes from the parent class? And keep the constrain that each class need to reside in a different file.
//Parent.mjs:
import Sub from "/.Sub.mjs"
export default class Parent {
static createSomething(){
new Sub();
}
}
//Sub.mjs:
import Parent from "/.Parent.mjs"
export default class Sub extends Parent {
contructor(){}
}
This question was originally posted here. But there is no solution under that question. If I really want to create a subclass from the superclass what code should I write?
The parent class should not need to know anything about subclass(es).
I don't see why the parent class would need a static method for creating a subclass,
but if you feel you really, really need that, then extend the Parent class object from within the Sub.mjs file:
Parent.mjs:
export default class Parent {
}
Sub.mjs:
import Parent from "/.Parent.mjs"
Parent.createSomething = function () {
return new Sub();
}
export default class Sub extends Parent {
constructor(){} // fixed typo here
}
Still, I think it is a bad idea to define such a function on the parent class. This looks like an XY problem. The original reason that made you look for such a function in the first place, certainly has a better way to be solved that doesn't involve a parent class that needs to know about a subclass.
I have a web component that only works when some properties are set, when I create the component with Document.createElement() I can't pass properties then an error happens in my component.
Is it possible to create the component by creating an instance of the component class or something similar and be able to pass parameters to it's constructor?
customElements.define('x-card', class extends HTMLDivElement {
//...
}, { extends: 'div' });
You can create a new instance using new WCard. This requires having access to the class though.
Please note that custom element names preferrably should not start with x-.
So change your code:
export class WCard extends HTMLDivElement {
//...
}
customElements.define('w-card', WCard, { extends: 'div' });
window.WCard = WCard;
This allows you to call new on the class globally, or if your code imports the class.
const wcard = new WCard(...args);
I read that using static for propTypes puts the it on the class instead of the instance of the React component. I don't get the difference between putting something on the class vs. the instance though. Why is propTypes on the class but not methods like render and componentDidMount, or other custom made methods inside the component?
It's for the same reason as the keyword static. This is un-changing static metadata that helps describe your class. It can be accessed without needing to instantiate your class (accessed without calling the constructor).
class example extends Component {
static propTypes = {
something: PropTypes.object,
}
static displayName = "ExampleDisplay";
render() {
return <div />;
}
}
// I can access static properties here directly
var types = example.propTypes;
var name = example.displayName;
// I can NOT access the render method without instantiating the class.
var instance = new example(); // <- this calls the constructor and creates an instance.
var renderFn = instance.render;
The question is really: why should I need to create the class just to read the propTypes or displayName? you shouldn't need to. that's why you have static.
I have the following ReactJS class:
import React from 'react'
export class Content extends React.Component {
static getValue(key) {
return key
}
render() {
let value = this.getValue(this.props.valueKey);
return <span dangerouslySetInnerHTML={{__html: value}} />
}
}
But I have the following error:
TypeError: this.getValue is not a function
I don't understand. Is this the good way to call a static function? I think react is doing something with statics, but I don't know what.
A static method needs to be accessed on the class not an instance. So in your case, use:
Content.getValue()
However, a static method won't be able to access this -- I don't think you want the method to be static based on your code sample above.
More: Static Members in ES6
You can access from within the class as this.constructor.getValue.
Edit: I've added a JSFiddle here. The only change I made was adding the function call from the constructor and removing the dangerously set innerHTML - As shown, you can access the getValue static from this.constructor, and works just fine.
I couldn't find the answer in the docs, so I'm asking here. What exactly is the binding context passed to the bind method of custom element. Is it simply equal to router's currently active ViewModel? At least, that's what I've found out so far.
Why isn't it the element's parent (in the terms of DOM) VM?
with this code
#customElement("myelem")
#inlineView("<template><content></content></template>")
export class MyElem{
bind(ctx){
console.log(ctx);
}
}
// welcome.html
<myelem>
<h3>inside myelem</h3>
<myelem>
<h4>inside inside ... </h4>
</myelem>
</myelem>
the output in the console is just current viewmodel (Welcome) printed twice.
I'd expect it to be Welcome for the first (outer) myelem, but MyElem for the second (inner) occurance...
Please explain why am I wrong here, and how can the inner custom element be aware of it's actual context (by which I mean the outer one in the case above), without using ugly hacks like creating secret property in the "shared" context (the one which actually gets passed to both of them)
In terms of data-binding, both elements are bound to the same binding context. Consider this example:
<div foo.bind="bar">
<div foo.bind="bar"></div>
</div>
You would expect both <div> elements to have the same binding context right? Both element's foo property should be bound to the same model's bar property. The same holds true in this scenario:
<myelem foo.bind="bar">
<myelem foo.bind="bar"></myelem>
</myelem>
Both instances of <myelem> are bound to the same binding context / model.
If I understand the question correctly, you would like an elegant way to give the inner MyElem class instance a reference to the outer MyElem class instance. Luckily, you're using Aurelia so there is a very nice way to do this... declare it as a dependency using the inject decorator:
import {inject, Parent} from 'aurelia-dependency-injection';
import {customElement} from 'aurelia-framework';
#customElement("myelem")
#inject(Parent.of(MyElem))
export class MyElem {
constructor(parent) {
this.parent = parent;
}
...
}
There's one caveat however...
The Aurelia dependency-injection container's default behavior is to create an instance of the requested item if an instance is not found in the container. This means that #inject(Parent.of(MyElem)) is not quite what we want. In situations where there is no parent MyElem instance the container will create one for us instead of returning null. Normally we'd use #inject(Optional.of(MyElem)) to tell the container to give us the instance, only when it exists in the container. I don't know of a way to combine Parent.of and Optional.of. I'll create an issue in the aurelia dependency-injection repository so we can get this feature added.
In the meantime, we can easily create our own Resolver that combines the behavior of Parent.of and Optional.of:
import {resolver} from 'aurelia-dependency-injection';
#resolver()
export class OptionalParent {
constructor(key) {
this.key = key;
}
get(container) {
if (container.parent && container.parent.hasResolver(this.key, false)) {
return container.parent.get(this.key)
}
return null;
}
static of(key) {
return new OptionalParent(key);
}
}
So the new version of our MyElem class would look like this:
import {inject} from 'aurelia-dependency-injection';
import {customElement} from 'aurelia-framework';
import {OptionalParent} from './optional-parent';
#customElement("myelem")
#inject(OptionalParent.of(MyElem))
export class MyElem {
constructor(parent) {
this.parent = parent;
}
...
}
Here's a working example. Check the console for log messages showing the result:
https://gist.run/?id=1a84e0a466fb928aa075