surveyjs / survey-library

Free JavaScript form builder library with integration for React, Angular, Vue, jQuery, and Knockout.
https://surveyjs.io/form-library
MIT License
4.23k stars 818 forks source link

Colorful Rate Items #6135

Closed JaneSjs closed 1 year ago

JaneSjs commented 1 year ago

Request to Colorize items: 1, 2, 3... 10

Examples: image

image

Originally posted by @JaneSjs in https://github.com/surveyjs/survey-library/issues/5149#issuecomment-1492864405

JaneSjs commented 1 year ago

TODO: create a demo with a custom color property and a custom rating item template.

JaneSjs commented 1 year ago

The following example demonstrates how to override rendering for Rating items and add a color property for an individual rate item.

Survey JSON Model

export const json = {
  elements: [
    {
      type: "rating-colored",
      name: "satisfaction-numeric",
      title: "How satisfied are you with our product?",
      rateValues: [
        { value: 0, text: "0", color: "#EA3532" },
        { value: 1, text: "1", color: "#F74445" },
        { value: 2, text: "2", color: "#FF6443" },
        { value: 3, text: "3", color: "#EDB188" },
        { value: 4, text: "4", color: "#FFA62B" },
        { value: 5, text: "5", color: "#FFC001" },
        { value: 6, text: "6", color: "#E3C301" },
        { value: 7, text: "7", color: "#C0CA00" },
        { value: 8, text: "8", color: "#9CCC02" },
        { value: 9, text: "9", color: "#79CA03" },
        { value: 10, text: "10", color: "#31B000" }
      ]
    }
  ],
  showQuestionNumbers: "off"
};

Custom Rating Scale question

import React, { createElement } from "react";
import { QuestionRatingModel, ElementFactory, Serializer } from "survey-core";
import {
  ReactElementFactory,
  RatingItem,
  SurveyQuestionRating,
  ReactQuestionFactory
} from "survey-react-ui";

Serializer.addProperty("itemvalue", {
  name: "color",
  isLocalible: true
});
class ColoredRatingItem extends RatingItem {
  get question() {
    return this.props.question;
  }
  get item() {
    return this.props.item;
  }
  get index() {
    return this.props.index;
  }
  get color() {
    return this.item.locText.owner.color;
  }
  getStateElement() {
    return this.item;
  }
  render() {
    var itemText = this.renderLocString(this.item.locText);
    var mycolor = this.color;
    return (
      <label
        className="sd-rating__item sd-rating__item--allowhover sd-rating__item--fixed-size"
        style={{ "background-color": mycolor }}
      >
        <input
          type="radio"
          className="sv-visuallyhidden"
          name={this.question.name}
          id={this.question.getInputId(this.index)}
          value={this.item.value}
          disabled={this.isDisplayMode}
          checked={this.question.value == this.item.value}
          onClick={this.props.handleOnClick}
          onChange={() => {}}
          aria-label={this.question.ariaLabel}
          aria-describedby={this.question.ariaDescribedBy}
        />
        <span className="sd-rating__item-text">{itemText}</span>
      </label>
    );
  }
}
ReactElementFactory.Instance.registerElement("colored-item", (props) => {
  return React.createElement(ColoredRatingItem, props);
});

const customType = "rating-colored";

class CustomRatingModel extends QuestionRatingModel {
  getType() {
    return customType;
  }
  get itemComponentName() {
    return "colored-item";
  }
}

Serializer.addClass(
  customType,
  [],
  function () {
    return new CustomRatingModel("");
  },
  "rating"
);
export function registerColoredRating() {
  ElementFactory.Instance.registerElement(customType, (name) => {
    return new CustomRatingModel(name);
  });
  ReactQuestionFactory.Instance.registerQuestion(customType, (props) => {
    return createElement(SurveyQuestionRating, props);
  });
}

index.css

.sd-question__content fieldset {
  display: flex;
  flex-direction: row;
  border: none;
  flex-wrap: wrap;
}
.svc-rating-question-content .sd-question__content {
  padding-left: 48px;
}

image

Please refer to the following Code Sandbox demos:

In Survey Creator, users can define individual rating item colors using the Property Grid editor: image

JaneSjs commented 1 year ago

With v1.9.113 and newer, it is possible to implement a custom Rating item component: Rating Scale: Custom Item Component Support. With this option, you can register a custom item component and apply a different background color based on a rate item value.