Hi team,
May I know how could we simulate the rating widget system, let say 1 - 5 star with the existing webix component?
https://snippet.webix.com/jh9tsto9
@integral It is perfect...
I expanded on it to add editor support:
rating widget:
export function renderRating(value: number, readOnly: boolean = false, height: number = 20, id?: number, scale: number = 5) { id = id || webix.uid() let div = '<input type="hidden" id="' + id + '" value="' + value + '" />' if (!readOnly) { div += '<span class="webix_icon webix_rating_zero mdi mdi-close" data-value="0"></span>' } for (let i = 0; i < scale; i++) { div += '<span class="webix_icon webix_rating_point mdi mdi-star' if (value > i) { div += ' webix_rating_selected' } div += '" style="line-height:' + height + 'px;"' div += ' data-value="' + (i + 1) + '"></span>' } return div } webix.protoUI({ name: 'rating', $cssName: 'text', $init: function () { this.on_click.webix_rating_point = function (e, id, target) { if (!this.config.readonly) { this.setValue(target.getAttribute('data-value')) } } this.on_click.webix_rating_zero = function (e, id, target) { if (!this.config.readonly) { this.setValue(target.getAttribute('data-value')) } } }, $renderInput: function (config, div, id: number) { const value = parseInt(config.value || 0) div = renderRating(value, config.readonly as boolean, config.cheight as number, id) return webix.ui.text.prototype.$renderInput.apply(this, [config, div, id] as any) }, $renderIcon: function () { return '' }, $setValue: function () { this.refresh() }, $getValue: function () { return this.config.value || 0 } }, webix.ui.text)
editor:
webix.editors.rating = { focus: function () { }, onRatingClick(el: HTMLElement) { const val: number = parseInt(el.dataset.value as string) this.setValue(val) }, getValue: function () { return this.getInputNode(this.node).value }, setValue: function (value) { this.getInputNode(this.node).value = value this.node.innerHTML = renderRating(value) const stars = this.node.querySelectorAll('.webix_rating_point') as HTMLElement[] stars.forEach(el => { el.addEventListener('click', () => this.onRatingClick(el)) }) const zero = this.node.querySelector('.webix_rating_zero') as HTMLElement zero.addEventListener('click', () => this.onRatingClick(zero)) }, getInputNode: function () { return this.node.firstChild }, render: function (value: number = 0): HTMLElement { return webix.html.create('div', { class: 'webix_dt_editor rating' }, renderRating(value) ) } }
scss:
.webix_rating_zero { display: none; position: relative; top: 1px; color: $grey !important; cursor: pointer; &:hover { color: $font-color !important; } } .webix_dt_editor.rating { .webix_rating_zero { display: initial; } .webix_icon.webix_rating_point { cursor: pointer; color: $grey !important; &:hover { color: $gold !important; } &.webix_rating_selected { color: $gold !important; &:hover { color: darken($gold, 10%) !important; } } } } .webix_dt_editor.rating { padding-left: 12px; } .webix_icon.webix_rating_point { color: transparent !important; &.webix_rating_selected { color: $gold !important; } }
column editor usage:
column.editor = 'rating' column.template = renderRating(3) // Initial value
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
https://snippet.webix.com/jh9tsto9
@integral It is perfect...
I expanded on it to add editor support:
rating widget:
editor:
scss:
column editor usage: