javascripthtmlcssnouislider

How to initialize the nouislider only once? noUISlider — `Uncaught Error: Slider was already initialized`


I am trying to create a range slider using nouislider. I will get the min and max values using input field. And on clicking a create button a range slider will be created.

function create_range()
{

      const slider = document.getElementById('sliderPrice');

      const min_val  = document.getElementById('min').value ;
      const max_val  = document.getElementById('max').value;
      const step      = 5; // to move in 5 steps

      const filterInputs = document.querySelectorAll('input.filter__input');

      // slider.noUiSlider.reset();

      var rangeMin = parseInt(min_val);
      var rangeMax = parseInt(max_val);


       noUiSlider.create(slider, {
         start: [rangeMin, rangeMax],
         connect: true,
         // step: step, // if removed it will be in range ,smooth drag
         range: {
             'min': rangeMin,
             'max': rangeMax
         },
        
        pips: {
          mode: 'count',
          values: 5 // to split the pips
        },
        // make numbers whole
         format: {
           to: value => value,
           from: value => value
         }
      });



       // bind inputs with noUiSlider 
       slider.noUiSlider.on('update', (values, handle) => { 
         var intvalue = Math.ceil( values[handle] ); //Round a number upward to its nearest integer:
         filterInputs[handle].value = values[handle];
          // slider.noUiSlider.reset(); 
       });


       filterInputs.forEach((input, indexInput) => { 
         input.addEventListener('change', () => {
           slider.noUiSlider.setHandle(indexInput, input.value);
         })
       });

                 // slider. noUiSlider. destroy();



     
} 
/*! nouislider - 14.6.0 - 6/27/2020 */
/* Functional styling;
 * These styles are required for noUiSlider to function.
 * You don't need to change these rules to apply your design.
 */
.noUi-target,
.noUi-target * {
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-user-select: none;
  -ms-touch-action: none;
  touch-action: none;
  -ms-user-select: none;
  -moz-user-select: none;
  user-select: none;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.noUi-target {
  position: relative;
}
.noUi-base,
.noUi-connects {
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
}
/* Wrapper for all connect elements.
 */
.noUi-connects {
  overflow: hidden;
  z-index: 0;
}
.noUi-connect,
.noUi-origin {
  will-change: transform;
  position: absolute;
  z-index: 1;
  top: 0;
  right: 0;
  -ms-transform-origin: 0 0;
  -webkit-transform-origin: 0 0;
  -webkit-transform-style: preserve-3d;
  transform-origin: 0 0;
  transform-style: flat;
}
.noUi-connect {
  height: 100%;
  width: 100%;
}
.noUi-origin {
  height: 10%;
  width: 10%;
}
/* Offset direction
 */
.noUi-txt-dir-rtl.noUi-horizontal .noUi-origin {
  left: 0;
  right: auto;
}
/* Give origins 0 height/width so they don't interfere with clicking the
 * connect elements.
 */
.noUi-vertical .noUi-origin {
  width: 0;
}
.noUi-horizontal .noUi-origin {
  height: 0;
}
.noUi-handle {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  position: absolute;
}
.noUi-touch-area {
  height: 100%;
  width: 100%;
}
.noUi-state-tap .noUi-connect,
.noUi-state-tap .noUi-origin {
  -webkit-transition: transform 0.3s;
  transition: transform 0.3s;
}
.noUi-state-drag * {
  cursor: inherit !important;
}
/* Slider size and handle placement;
 */
.noUi-horizontal {
  height: 18px;
}
.noUi-horizontal .noUi-handle {
  width: 34px;
  height: 28px;
  right: -17px;
  top: -6px;
}
.noUi-vertical {
  width: 18px;
}
.noUi-vertical .noUi-handle {
  width: 28px;
  height: 34px;
  right: -6px;
  top: -17px;
}
.noUi-txt-dir-rtl.noUi-horizontal .noUi-handle {
  left: -17px;
  right: auto;
}
/* Styling;
 * Giving the connect element a border radius causes issues with using transform: scale
 */
.noUi-target {
  background: #FAFAFA;
  border-radius: 4px;
  border: 1px solid #D3D3D3;
  box-shadow: inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;
}
.noUi-connects {
  border-radius: 3px;
}
.noUi-connect {
  background: #3FB8AF;
}
/* Handles and cursors;
 */
.noUi-draggable {
  cursor: ew-resize;
}
.noUi-vertical .noUi-draggable {
  cursor: ns-resize;
}
.noUi-handle {
  border: 1px solid #D9D9D9;
  border-radius: 3px;
  background: #FFF;
  cursor: default;
  box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #EBEBEB, 0 3px 6px -3px #BBB;
}
.noUi-active {
  box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #DDD, 0 3px 6px -3px #BBB;
}
/* Handle stripes;
 */
.noUi-handle:before,
.noUi-handle:after {
  content: "";
  display: block;
  position: absolute;
  height: 14px;
  width: 1px;
  background: #E8E7E6;
  left: 14px;
  top: 6px;
}
.noUi-handle:after {
  left: 17px;
}
.noUi-vertical .noUi-handle:before,
.noUi-vertical .noUi-handle:after {
  width: 14px;
  height: 1px;
  left: 6px;
  top: 14px;
}
.noUi-vertical .noUi-handle:after {
  top: 17px;
}
/* Disabled state;
 */
[disabled] .noUi-connect {
  background: #B8B8B8;
}
[disabled].noUi-target,
[disabled].noUi-handle,
[disabled] .noUi-handle {
  cursor: not-allowed;
}
/* Base;
 *
 */
.noUi-pips,
.noUi-pips * {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.noUi-pips {
  position: absolute;
  color: #999;
}
/* Values;
 *
 */
.noUi-value {
  position: absolute;
  white-space: nowrap;
  text-align: center;
}
.noUi-value-sub {
  color: #ccc;
  font-size: 10px;
}
/* Markings;
 *
 */
.noUi-marker {
  position: absolute;
  background: #CCC;
}
.noUi-marker-sub {
  background: #AAA;
}
.noUi-marker-large {
  background: #AAA;
}
/* Horizontal layout;
 *
 */
.noUi-pips-horizontal {
  padding: 10px 0;
  height: 80px;
  top: 100%;
  left: 0;
  width: 100%;
}
.noUi-value-horizontal {
  -webkit-transform: translate(-50%, 80%);
  transform: translate(-50%, 80%);
}
.noUi-rtl .noUi-value-horizontal {
  -webkit-transform: translate(50%, 50%);
  transform: translate(50%, 50%);
}
.noUi-marker-horizontal.noUi-marker {
  margin-left: -1px;
  width: 2px;
  height: 5px;
  top: 1%;  /* jas*/
}
.noUi-marker-horizontal.noUi-marker-sub {
  height: 10px;
}
.noUi-marker-horizontal.noUi-marker-large {
  height: 15px;
  top: 1%;/* jas*/
}
/* Vertical layout;
 *
 */
.noUi-pips-vertical {
  padding: 0 10px;
  height: 100%;
  top: 0;
  left: 100%;
}
.noUi-value-vertical {
  -webkit-transform: translate(0, -50%);
  transform: translate(0, -50%);
  padding-left: 25px;
}
.noUi-rtl .noUi-value-vertical {
  -webkit-transform: translate(0, 50%);
  transform: translate(0, 50%);
}
.noUi-marker-vertical.noUi-marker {
  width: 5px;
  height: 2px;
  margin-top: -1px;
}
.noUi-marker-vertical.noUi-marker-sub {
  width: 10px;
}
.noUi-marker-vertical.noUi-marker-large {
  width: 15px;
}
.noUi-tooltip {
  display: block;
  position: absolute;
  border: 1px solid #D9D9D9;
  border-radius: 3px;
  background: #fff;
  color: #000;
  padding: 5px;
  text-align: center;
  white-space: nowrap;
}
.noUi-horizontal .noUi-tooltip {
  -webkit-transform: translate(-50%, 0);
  transform: translate(-50%, 0);
  left: 50%;
  bottom: 120%;
}
.noUi-vertical .noUi-tooltip {
  -webkit-transform: translate(0, -50%);
  transform: translate(0, -50%);
  top: 50%;
  right: 120%;
}
.noUi-horizontal .noUi-origin > .noUi-tooltip {
  -webkit-transform: translate(50%, 0);
  transform: translate(50%, 0);
  left: auto;
  bottom: 10px;
}
.noUi-vertical .noUi-origin > .noUi-tooltip {
  -webkit-transform: translate(0, -18px);
  transform: translate(0, -18px);
  top: auto;
  right: 28px;
}


/*  other styles */
 *, *:before, *:after {
   box-sizing: border-box;
   margin: 0;
   padding: 0;
   outline: none;
 }


 /* custom styles for UiSlider */
 .noUi-target {
   cursor: pointer;
 }
 .noUi-target :focus {
   outline: none;
 }

 .noUi-horizontal {
   height: 9px;
 }

 .noUi-connect {
   background: #9b26af;
 }

 .noUi-base {
   background: #DEDEDE;
 }

 .noUi-horizontal .noUi-handle {
   top: -6px;
   /*right: -15px;*/
   right: -12px;
   width: 22px;
   height: 22px;
   background: #9b26af;
   border: 2px solid #711fab;
   border-radius: 50%;
   box-shadow: unset;
   cursor: pointer;
   transition: transform 0.1s;
 }
 .noUi-horizontal .noUi-handle:before, .noUi-horizontal .noUi-handle:after {
   content: none;
 }
 .noUi-horizontal .noUi-handle:hover {
   transform: scale(1.1);
 }

 /* styles for filter */
 .filter {

  width: 500px;
  margin: 0 auto;
  /*border: 1px solid red;*/
   /*display: flex;
   flex-wrap: wrap;
   justify-content: space-between;
   max-width: 370px;
   border-radius: 10px;
   background: white;
   box-shadow: 0px 0px 50px 4px rgba(0, 0, 0, 0.75);
   padding: 20px;*/
 }

 .filter__label {
   position: relative;
   cursor: pointer;
 }
 .filter__label:before {
   position: absolute;
   left: 8px;
   top: 50%;
   transform: translateY(-50%);
   color: #999999;
   font-size: 14px;
 }
 .filter__label:nth-child(1):before {
   content: "from";
 }
 .filter__label:nth-child(2):before {
   content: "to";
 }

 .filter__input {
   height: 35px;
   border: 2px solid #711fab;
   border-radius: 5px;
   padding: 0 10px 0 40px;
   cursor: pointer;
   max-width: 160px;
 }
 .filter__input:focus {
   background: rgba(155, 38, 175, 0.2);
 }

 .filter__slider-price {
   width: 100%;
    margin: 20px 0;
    margin-bottom: 75px;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/14.6.0/nouislider.js"></script>
<div class="container">

        min:
        <input  type="text" id="min" name="product" value="">

        max:
        <input  type="text" id="max" name="product" value="">

        <input type="button" value="create range" onclick="create_range()">
    </div>

   

      <div class="filter">

          

         <div id="sliderPrice" class="filter__slider-price" data-min="0" data-max="100" data-step="5"></div>

          <label class="filter__label">
            <input type="text" class="filter__input" id="min_val">
          </label>  

          <label class="filter__label">
            <input type="text" class="filter__input" id="max_val">
          </label>
          
      </div>

Next time when I change the input field value and click create button it is showing error as "noUiSlider (14.6.0): Slider was already initialized."

How to initialize the nouislider once.Or how to reset the nouislider?


Solution

  • There is no way you can reinitialize the existing slider as of now. But you can definitely destroy the slider and create a new one. You'll need to add a check if the slider object is present or not, based on that destroy existing and then create a new one.

    The JS code will look like this.

    let slider;
    
    function destroyExistingSlider(){
      if(slider && slider.noUiSlider){
        slider.noUiSlider.destroy();
      }
    }
    
    function create_range()
    {
      destroyExistingSlider();
      slider = document.getElementById('sliderPrice');
      const min_val  = document.getElementById('min').value ;
      const max_val  = document.getElementById('max').value;
      const step      = 5; // to move in 5 steps
    
      const filterInputs = document.querySelectorAll('input.filter__input');
    
      // slider.noUiSlider.reset();
    
      var rangeMin = parseInt(min_val);
      var rangeMax = parseInt(max_val);
    
        noUiSlider.create(slider, {
         start: [rangeMin, rangeMax],
         connect: true,
         // step: step, // if removed it will be in range ,smooth drag
         range: {
             'min': rangeMin,
             'max': rangeMax
         },
        
        pips: {
          mode: 'count',
          values: 5 // to split the pips
        },
        // make numbers whole
         format: {
           to: value => value,
           from: value => value
         }
      });
       
    
       // bind inputs with noUiSlider 
       slider.noUiSlider.on('update', (values, handle) => { 
         var intvalue = Math.ceil( values[handle] ); //Round a number upward to its nearest integer:
         filterInputs[handle].value = values[handle];
          // slider.noUiSlider.reset(); 
       });
    
       filterInputs.forEach((input, indexInput) => { 
         input.addEventListener('change', () => {
           slider.noUiSlider.setHandle(indexInput, input.value);
         })
       });
    
     
    

    }