Home > OS >  No same value picked for multiple input range slider
No same value picked for multiple input range slider

Time:09-27

I would like to control all slider value in a function where no same number is picked twice for the slider value and if it's picking the same number, the slider should show an error and only if all slider contains a different value, it'll proceed to show the next button.

import React from 'react'
import subjectCategories from './categories';

export default function InterestScore() {

    const[range,setRange]=React.useState(
        {cyberSecurity:"1",
        projectManager:"1",
        developer:"1",
        productManager:"1",
        devOps:"1",
        marketer:"1",
        designer:"1",
        writer:"1"}
    );

    function handleChange(e) {
        setRange(prevRange=>{
            return (
                {...prevRange, [e.target.name]:e.target.value}
                
            )    
        })

        for(let i=0;i<8;i  ) {
            if(range[e.target.name]===e.target.value) {
                console.log("cannot pick same number twice");
            }
        }

    }

    for (let e of document.querySelectorAll('input[type="range"].slider-progress')) {
        e.style.setProperty('--value', e.value);
        e.style.setProperty('--min', e.min == '' ? '1' : e.min);
        e.style.setProperty('--max', e.max == '' ? '10' : e.max);
        e.addEventListener('input', () => e.style.setProperty('--value', e.value));
      }


  return (
    <div className='interest_score'>
        <div className='q_card'>
            <p>Score your level of interest in these job titles:</p>
            <div className='range_container'>
                {subjectCategories && subjectCategories.map((category) => {
                    return (
                            <div className='category_group'  key={category.id}>
                                <div className='labels'>
                                    <label className='range_label'>{category.subject}</label>
                                    <span>{range[category.name]}/10</span>
                                </div>
                                <input type='range' min='1' max='10' name={category.name}
                                className='styled-slider slider-progress'
                                 onChange={(e)=>handleChange(e)} value={range[category.name]}/>
                            </div>
                    );
                })}
            </div>
            <p>* You cannot pick a number twice</p>
            <button className='next'>Next</button>
        </div>
    </div>
  )
}
const subjectCategories = [
    
    {id:1,subject:"Cyber Security",name:"cyberSecurity"},
    {id:2,subject:"Project Manager",name:"projectManager"},
    {id:3,subject:"Developer",name:"developer"},
    {id:4,subject:"Product Manager",name:"productManager"},
    {id:5,subject:"DevOps",name:"devOps"},
    {id:6,subject:"Marketer",name:"marketer"},
    {id:7,subject:"Designer",name:"designer"},
    {id:8,subject:"Writer",name:"writer"}
]

export default subjectCategories;
.interest_score {
    margin:5rem 1rem 0 7rem;
    
}

.interest_score p {
    text-align:left;
    padding:1em 3em;
}

.range_container {
    margin-top:0.5em;
    padding:0.5em 2em;
    color:#ACB7EB;
    font-size:14px;
    display:flex;
    flex-wrap:wrap;
    justify-content:space-between;
    align-items:center;
 
}

.category_group {
 display:flex;
 flex-direction:column;
 align-items:flex-start;
 flex:1 0 45%;
 padding:1.5em 1em;

}

.range_container label {
    width:100%;
    text-align:left;
    
}

.labels {
    display:flex;
    justify-content:space-between;
    width:100%;
}

.labels span {
    color:black;
}

.q_card p:nth-of-type(2){
    color:#ACB7EB;
}

/*generated with Input range slider CSS style generator (version 20211225)
https://toughengineer.github.io/demo/slider-styler*/
input[type=range].styled-slider {
    height: 1.8em;
    width:100%;
    -webkit-appearance: none;
  }
  
  /*progress support*/
  input[type=range].styled-slider.slider-progress {
    --range: calc(var(--max) - var(--min));
    --ratio: calc((var(--value) - var(--min)) / var(--range));
    --sx: calc(0.5 * 1.4em   var(--ratio) * (100% - 1.4em));
  }
  
  input[type=range].styled-slider:focus {
    outline: none;
  }
  
  /*webkit*/
  input[type=range].styled-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 1.4em;
    height: 1.4em;
    border-radius: 50%;
    background: #FFFFFF;
    border: 4px solid rgba(204, 65, 116, 0.6);
    box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2);
    margin-top: calc(max((1em - 1px - 1px) * 0.5,0px) - max(1.4em * 0.5,4px));
  }
  
  input[type=range].styled-slider::-webkit-slider-runnable-track {
    height: 10px;
    border: 1px solid #b2b2b2;
    border-radius: 0.5em;
    background: #EFEFEF;
    box-shadow: none;
  }
  
  input[type=range].styled-slider::-webkit-slider-thumb:hover {
    background: rgba(241, 243, 253, 1);

  }
  
  input[type=range].styled-slider:hover::-webkit-slider-runnable-track {
    background: #E5E5E5;
    border-color: #9a9a9a;
  }
  
  input[type=range].styled-slider::-webkit-slider-thumb:active {
    background: rgba(241, 243, 253, 1);

  }
  
  input[type=range].styled-slider:active::-webkit-slider-runnable-track {
    background: #F5F5F5;
    border-color: #c1c1c1;
  }
  
  input[type=range].styled-slider.slider-progress::-webkit-slider-runnable-track {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%) 0/var(--sx) 100% no-repeat, #EFEFEF;
  }
  
  input[type=range].styled-slider.slider-progress:hover::-webkit-slider-runnable-track {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%) 0/var(--sx) 100% no-repeat, #E5E5E5;
  }
  
  input[type=range].styled-slider.slider-progress:active::-webkit-slider-runnable-track {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%) 0/var(--sx) 100% no-repeat, #F5F5F5;
  }
  
  /*mozilla*/
  input[type=range].styled-slider::-moz-range-thumb {
    width: max(calc(1.4em - 4px - 4px),0px);
    height: max(calc(1.4em - 4px - 4px),0px);
    border-radius: 50%;
    background: #FFFFFF;
    border: 4px solid rgba(204, 65, 116, 0.6);
    box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2);
  }
  
  input[type=range].styled-slider::-moz-range-track {
    height: max(calc(1em - 1px - 1px),0px);
    border: 1px solid #b2b2b2;
    border-radius: 0.5em;
    background: #EFEFEF;
    box-shadow: none;
  }
  
  input[type=range].styled-slider::-moz-range-thumb:hover {
    background: #FFFFFF;
  }
  
  input[type=range].styled-slider:hover::-moz-range-track {
    background: #E5E5E5;
    border-color: #9a9a9a;
  }
  
  input[type=range].styled-slider::-moz-range-thumb:active {
    background: #FFFFFF;
  }
  
  input[type=range].styled-slider:active::-moz-range-track {
    background: #F5F5F5;
    border-color: #c1c1c1;
  }
  
  input[type=range].styled-slider.slider-progress::-moz-range-track {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%) 0/var(--sx) 100% no-repeat, #EFEFEF;
  }
  
  input[type=range].styled-slider.slider-progress:hover::-moz-range-track {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%) 0/var(--sx) 100% no-repeat, #E5E5E5;
  }
  
  input[type=range].styled-slider.slider-progress:active::-moz-range-track {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%) 0/var(--sx) 100% no-repeat, #F5F5F5;
  }
  
  /*ms*/
  input[type=range].styled-slider::-ms-fill-upper {
    background: transparent;
    border-color: transparent;
  }
  
  input[type=range].styled-slider::-ms-fill-lower {
    background: transparent;
    border-color: transparent;
  }
  
  input[type=range].styled-slider::-ms-thumb {
    width: 1.4em;
    height: 1.4em;
    border-radius: 50%;
    background: #FFFFFF;
    border: 4px solid rgba(204, 65, 116, 0.6);
    box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2);
    margin-top: 0;
    box-sizing: border-box;
  }
  
  input[type=range].styled-slider::-ms-track {
    height: 1em;
    border-radius: 0.5em;
    background: #EFEFEF;
    border: 1px solid #b2b2b2;
    box-shadow: none;
    box-sizing: border-box;
  }
  
  input[type=range].styled-slider::-ms-thumb:hover {
    background: #FFFFFF;
  }
  
  input[type=range].styled-slider:hover::-ms-track {
    background: #E5E5E5;
    border-color: #9a9a9a;
  }
  
  input[type=range].styled-slider::-ms-thumb:active {
    background: #FFFFFF;
  }
  
  input[type=range].styled-slider:active::-ms-track {
    background: #F5F5F5;
    border-color: #c1c1c1;
  }
  
  input[type=range].styled-slider.slider-progress::-ms-fill-lower {
    height: max(calc(1em - 1px - 1px),0px);
    border-radius: 0.5em 0 0 0.5em;
    margin: -1px 0 -1px -1px;
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%);
    border: 1px solid #b2b2b2;
    border-right-width: 0;
  }
  
  input[type=range].styled-slider.slider-progress:hover::-ms-fill-lower {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%);
    border-color: #9a9a9a;
  }
  
  input[type=range].styled-slider.slider-progress:active::-ms-fill-lower {
    background: linear-gradient(90deg, #800165 0%, #D3014E 100%);
    border-color: #c1c1c1;
  }
  

CodePudding user response:

You can check if there are duplicate range values on different sliders like this:

const currentValues = Object.values(range);
const uniqueRangeValues = [...new Set(currentValues)];
const hasError = currentValues.length !== uniqueRangeValues.length;

And you get the hasError variable and use it in jsx like this:

{hasError ? (
      <p>* You cannot pick a number twice</p>
    ) : (
      <button className="next">Next</button>
 )}

You can take a look at this sandbox for a live working example of this solution.

  • Related