Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't extend from custom element #156

Closed
admosity opened this issue May 23, 2016 · 14 comments
Closed

Can't extend from custom element #156

admosity opened this issue May 23, 2016 · 14 comments

Comments

@admosity
Copy link

I am trying to extend a simple custom element using version 1.5.9:

xtag.register('x-span', {
  mixins: ['dataPoint', 'dataSource'],
  content: '<span></span>',
  methods: {
    render() {
      // some render logic...
    },
  },
});
xtag.register('x-money-span', {
  extends: 'x-span',
  methods: {
    render() {
      const span = xtag.queryChildren(this, 'span')[0];
      let data = this.data;
      let currency = this.getAttribute('currency');
      if (currency) {
        span.textContent = `${SomeDataService.getData('currency')[currency].symbol}${this.data}`;
      }
    },
  },
});

However, I am getting the following error:

Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'x-money-span'. The tag name specified in 'extends' is a custom element name. Use inheritance instead.

😢

@csuwildcat
Copy link
Member

That's not an X-Tag thing, it's how the standard Custom Elements API works.
Is there a reason you can't inherent from the previous custom element's
prototype using standard means?
On May 23, 2016 2:40 PM, "admosity" [email protected] wrote:

I am trying to extend a simple custom element using version 1.5.9:

xtag.register('x-span', {
mixins: ['dataPoint', 'dataSource'],
content: '',
methods: {
render() {
// some render logic...
},
},
});

xtag.register('x-money-span', {
extends: 'x-span',
methods: {
render() {
const span = xtag.queryChildren(this, 'span')[0];
let data = this.data;
let currency = this.getAttribute('currency');
if (currency) {
span.textContent = ${SomeDataService.getData('currency')[currency].symbol}${this.data};
}
},
},
});

However, I am getting the following error:

Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'x-money-span'. The tag name specified in 'extends' is a custom element name. Use inheritance instead.

😢


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
#156

@admosity
Copy link
Author

admosity commented May 23, 2016

Thanks for the quick reply!

I am fairly new to the library and to the Custom Elements API in general... What would be the correct way of referencing a registered tag?

I tried doing:

  xtag.register('x-money-span', {
  prototype: xtag.tags['x-span'].compiled.prototype,
  methods: {
    render() {
      const span = xtag.queryChildren(this, 'span')[0];
      let data = this.data;
      let currency = this.getAttribute('currency');
      if (currency) {
        span.textContent = `${SomeDataService.getData('currency')[currency].symbol}${this.data}`;
      }
    },
  },
});

But that doesn't seem to be working.

@admosity
Copy link
Author

It's not pretty, but this works:

import SomeDataService from '../core/SomeDataService';

let proto = Object.create(xtag.tags['x-span'].compiled.prototype);
let originalRender = proto.render.value;
proto.render = {
  enumberable: true,
  value: function () {
    originalRender.call(this);
    const span = xtag.queryChildren(this, 'span')[0];
    let data = this.data;
    let currency = this.getAttribute('currency');
    if (currency) {
      span.textContent = `${SomeDataService.getData(`currency.${currency}.symbol`)}${this.data}`;
    }
  },
};
xtag.register('x-money-span', {
  mixins: ['dataPoint', 'dataSource'],
  prototype: proto,
});

Is there a better way of doing this?

@csuwildcat
Copy link
Member

The code below should work, but I haven't tested it. Let me know, I want to make sure we are doing the most we can for your use-case.

var xSpan = xtag.register('x-span', {
  mixins: ['dataPoint', 'dataSource'],
  content: '<span></span>',
  methods: {
    render() {
      // some render logic
    },
  },
});

xtag.register('x-money-span', {
  prototype: xSpan.prototype,
  methods: {
    render: function() {
        xSpan.prototype.render.call(this, ARGS_HERE);
        // x-money-span render logic
    },
  }
});

@admosity
Copy link
Author

Ah, I did exactly that. Except for some reason the mixins and content don't propagate through and I have to redefine them. Here's my code:

import XSpan from './Span';
import SomeDataService from '../core/SomeDataService';

xtag.register('x-money-span', {
  mixins: ['dataPoint', 'dataSource'],
  prototype: XSpan.prototype,
  content: '<span></span>',
  methods: {
    render() {
      XSpan.prototype.render.call(this)
      const span = xtag.queryChildren(this, 'span')[0];
      let data = this.data;
      let currency = this.getAttribute('currency');
      if (currency) {
        span.textContent = `${SomeDataService.getData(`currency.${currency}.symbol`)}${this.data}`;
      }
    }
  }
});

@csuwildcat
Copy link
Member

I will setup a test case for this to figure out what's going on. I
definitely want to make sure the mixins and content carry over.
On May 23, 2016 6:26 PM, "admosity" [email protected] wrote:

Ah, I did exactly that. Except for some reason the mixins and content
don't propagate through and I have to redefine them. Here's my code:

import XSpan from './Span';import SomeDataService from '../core/SomeDataService';
xtag.register('x-money-span', {
mixins: ['dataPoint', 'dataSource'],
prototype: XSpan.prototype,
content: '',
methods: {
render() {
XSpan.prototype.render.call(this)
const span = xtag.queryChildren(this, 'span')[0];
let data = this.data;
let currency = this.getAttribute('currency');
if (currency) {
span.textContent = ${SomeDataService.getData(currency.${currency}.symbol)}${this.data};
}
}
}
});


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#156 (comment)

@admosity
Copy link
Author

Added test cases in #157

@csuwildcat
Copy link
Member

@admosity can you create a live test case using JSBin or something that shows your breaking example?

@admosity
Copy link
Author

@csuwildcat I actually just replicated the issue. The lifecycle hooks were not triggering from the mixins. I have added a new test case to the PR #157

@csuwildcat
Copy link
Member

@admosity I confirmed your issue, and am actively working on this.

@csuwildcat
Copy link
Member

@admosity I have a brand new build up on master that I have not pushed out to release yet. I believe it accounts for all forms of composition and inheritance, including mixins. Can you please test it and let me know?

@admosity
Copy link
Author

@csuwildcat sorry, been swamped with work and have not gotten around to this. I will let you know when I do. Thanks for getting it covered!

@csuwildcat
Copy link
Member

I am closing this out for now given the changes seem to be working well for everyone - please reopen if you have any further issues with this.

@armartinez
Copy link

armartinez commented Jul 13, 2016

I'm extending a custom element by using the prototype property specified by csuwildcat (would be nice if extends also worked for custom elements).
I noticed that when calling an overwritten method the base and the overwritten methods are called in order, is this the expected behaviour ? I would expect that only the latter gets called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants