Skip to content

Instantly share code, notes, and snippets.

@sarvabowmen
Last active April 8, 2021 17:27
Show Gist options
  • Select an option

  • Save sarvabowmen/26479212232f07bada32a3007c15cb7b to your computer and use it in GitHub Desktop.

Select an option

Save sarvabowmen/26479212232f07bada32a3007c15cb7b to your computer and use it in GitHub Desktop.
Convert Rating react component as web component
<div style="display:flex">
<div style="padding:150px 500px">
<h1>Rating element with webcomponents</h1>
<rating-element maxValue=5 value=0 onratingupdatedevt="onratingupdatedevt"></rating-element>
<div id="result"></div>
<button id="btnReset">Reset</button>
</div>
<script>
const btn = document.getElementById('btnReset');
const reactEl = document.getElementsByTagName('rating-element')[0];
btn.onclick = function (event) {
reactEl.setAttribute("value", 0);
var reactResultEl = document.getElementById('result');
reactResultEl.innerHTML = "You have rated " + event.detail;
};
reactEl.addEventListener("onratingupdatedevt", function (event) {
var reactResultEl = document.getElementById('result');
reactResultEl.innerHTML = "You have rated " + event.detail;
});
</script>
import './index.css';
import * as serviceWorker from './serviceWorker';
import './ReactElement';
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
import * as React from 'react';
import PropTypes from 'prop-types';
class RatingComponent extends React.Component {
static propTypes = {
maxValue: PropTypes.number,
value: PropTypes.number,
onRatingUpdatedEvt: PropTypes.func
}
static defaultProps = {
maxValue: 5
}
constructor(props){
super(props);
this.starList = [];
this.value = 0;
this.maxValue = props.maxValue;
this.state = { starList : [] };
}
componentDidMount(){
this.createStars(this.value);
}
setValue(newVal) {
this.value = newVal;
this.createStars(this.value);
this.props.onratingupdatedevt({ detail: this.value });
}
createStars(starsSelected) {
let starList = [];
for(let i=0; i<=this.maxValue; i++) {
if(i<=starsSelected){
starList.push(<span key={i} className="rating" onMouseOver={()=> this.createStars(i)} onMouseOut={()=> { this.createStars(this.value) }} onClick={ ()=> this.setValue(i) } >&#x2605;</span>);
} else {
starList.push(<span key={i} className="rating" onMouseOver={()=> this.createStars(i)} onMouseOut={()=> { this.createStars(this.value) }} onClick={ ()=> this.setValue(i) }>&#x2606;</span>);
}
}
this.starList = starList;
this.setState({ starList: starList });
}
render(){
return (
<div>
{this.state.starList}
</div>
)
}
}
RatingComponent.propTypes = {
maxValue: PropTypes.number,
value: PropTypes.number,
onratingupdatedevt: PropTypes.func
};
export default RatingComponent;
import * as React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import RatingComponent from './RatingComponent.js';
class ReactElement extends HTMLElement {
constructor() {
super();
this.observer = new MutationObserver(() => this.update());
this.observer.observe(this, { attributes: true });
}
connectedCallback() {
this._innerHTML = this.innerHTML;
this.mount();
}
disconnectedCallback() {
this.unmount();
this.observer.disconnect();
}
update() {
this.unmount();
this.mount();
}
mount() {
const props = {
...this.getProps(this.attributes),
...this.getEvents(),
children: this.parseHtmlToReact(this.innerHTML)
};
render(<RatingComponent {...props} />, this);
}
unmount() {
unmountComponentAtNode(this);
}
parseHtmlToReact(html) {
return html;
}
getProps(attributes) {
return [ ...attributes ]
.filter(attr => attr.name !== 'style')
.map(attr => this.convert(attr.name, attr.value))
.reduce((props, prop) =>
({ ...props, [prop.name]: prop.value }), {});
}
getEvents() {
return Object.values(this.attributes)
.filter(key => /on([a-z].*)/.exec(key.name))
.reduce((events, ev) => ({
...events,
[ev.name]: args =>
this.dispatchEvent(new CustomEvent(ev.name, { ...args }))
}), {});
}
convert(attrName, attrValue) {
let value = attrValue;
if (attrValue === 'true' || attrValue === 'false')
value = attrValue === 'true';
else if (!isNaN(attrValue) && attrValue !== '')
value = +attrValue;
else if (/^{.*}/.exec(attrValue))
value = JSON.parse(attrValue);
return {
name: attrName,
value: value
};
}
}
customElements.define('rating-element', ReactElement);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment