JSFiddle - React, Tailwind, and code Playground

by Erik Jan de Wilde

HTML

<html>
  <header>
    <meta charset="UTF-8" />
    <link rel="stylesheet" id="stylesheet" href="style.css" type="text/css" media="all" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.8/d3.min.js"></script>
  </header>

  <body>
    <div id="vueapp">
      <div class="selectionColumn">
        <h2>Choices</h2>
        <ul>
          <li v-for="item in ChoiceOptions">
            <input v-on:change="adjustVisual()" :value="item" type="radio" v-model="selectedOptions" />
            {{ item }}
          </li>
        </ul>
        <h2>Selection</h2>
        <span>Choice:: {{ selectedOptions }}<br /></span>
        <span>Filtered Data: {{ FilteredData }}<br /></span>
      </div>
      <div id="D3">
        <h2>Visual</h2>
        <div id="visual"></div>
      </div>
    </div>
  </body>
  <footer>
    <script src="ep.js"></script>
  </footer>

</html>

CSS

.selectionColumn,
.selectedData {
  width: 25%;
  height: 250px;
  padding: 5px 5px 5px 5px;
  float: left;
  border: 1px solid blue;
  border-radius: 5px;
  margin-left: 10px;
}

#D3 {
  width: 60%;
  height: 250px;
  padding: 5px 5px 5px 5px;
  float: left;
  border: 1px solid blue;
  border-radius: 5px;
  margin-left: 10px;
}

ul li {
  list-style: none;
  cursor: pointer;
  height: 18px;

JavaScript

var choiceOptions = ['A', 'B'];
var dataBegin = [{
  score: 150,
  choice: 'A'
}, {
  score: 350,
  choice: 'B'
}];

var app = new Vue({
  el: '#vueapp',
  data: {
    start: dataBegin,
    selectedOptions: [],
    ChoiceOptions: choiceOptions
  },
  computed: {
    FilteredData: function() {
      FilteredData = this.start.filter(point => {
        return this.selectedOptions.includes(point.choice);
      })
      return FilteredData;
    }
  },
  methods: {
    adjustVisual: function(event) {
    	this.$nextTick(()=>{
            this.updateVisual();
          });
      
    },
    updateVisual() {
      var animationSpeed = 2000;
      var barwidth = 400;
      //circle
      d3.select("svg")
        .selectAll("circle")
        .data(this.FilteredData)
        .transition().duration(animationSpeed)
        .attr("cx", function(d) {
          return d.score
        });
      //circle label
      d3.select("svg")
        .selectAll("text")
        .data(this.FilteredData)
        .transition().duration(animationSpeed)
        .text(function(d, i) {
          return d.choice
        })
        .attr("x", function(d) {
          return d.score
        });

    },
    drawVisual() {
      var svg = d3.select("#visual").append("svg").attr("width", 500).attr("height", 200);
      var barwidth = 400;
      //bar
      svg.append("rect")
        .attr("height", 50)
        .attr("width", barwidth)
        .attr("rx", 5)
        .attr("ry", 5)
        .style("fill", "green")
        .style("opacity", 1)
        .style("stroke", "red")
        .style("stroke-width", "0px")
        .attr("y", 0)
        .attr("x", 50);
      //circle
      svg.append("circle")
        .attr("cy", 25)
        .attr("cx", 75)
        .style("fill", "#FFCA00")
        .style("stroke", "maroon")
        .style("stroke-width", "3px")
        .attr("r", 20);

      //circle label      
      svg.append("text")
        .attr("font-weight", "normal")
        .attr("stroke-width", "0")
       ...