Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add a property to my custom element and be able to fire an action on its value change

In fact the title does not fully cover what I'm after. I have created my own select element. It's made of some div, ul/li and hidden input elements.It's of course got the markup and javascript part. Here's the html:

<div id="ddlCars" class="ma-select" style="width:350px;">
        <div class="ma-select-box"><input class="ma-select-box-filter" type="text"></div>
        <div class="ma-select-options">
            <ul class="ma-select-ul">
                <li class="ma-select-li ma-visible-option" optvalue="7">MERCEDES</li>
                <li class="ma-select-li ma-visible-option" optvalue="10">BMW</li>
                <li class="ma-select-li ma-visible-option" optvalue="14">AUDI</li>
                <li class="ma-select-li ma-visible-option" optvalue="3">VOLKSWAGEN</li>
            </ul>
        </div>
        <input class="ma-select-hidden"  type="hidden">
    </div>

The javascript code is just a bunch of functions that catch events like click, hover, keyup etc and are bound to the above elements (by class) on ready method. I haven't declared any type for this custom select.

With a normal DOM select element I am able to do this:

 document.getElementById("mySelect").selectedIndex=0;

Now I would like to achieve the something similar. I can find the wrapper div by id or class name. But is there a way I can do something something like this?

$('#ddlCars').selectedIndex=1;

So somehow, I need to add a property to my custom select and catch its change to set the selelcted value to the corresponding li element.

like image 330
Mikayil Abdullayev Avatar asked Oct 19 '22 12:10

Mikayil Abdullayev


1 Answers

to get the same behaviour as the select element you might want to extend the element like you would to a normal class. perhaps use a library like Polymer, github.com/richardanaya/webblock or github.com/SaulDoesCode/Crafter.js to design your custom element this way.

Otherwise should you implement it manually use getters and setters.
You would have to use Object.defineProperty to create such custom behaviour using getters and setters on elements.

here is a nifty little function to make that easier

   function newGetSet(element ,key, get, set) {
         Object.defineProperty(element, key, {
           set: set,
           get: get
         });
   }
   // then use it - just a rough example 
   newGetSet( myElement , 'selectedIndex' , index => {
      // perhaps then apply a class or something to make it active
      document.querySelectorAll('ul > li')[index].classList.add('active');
   }, () => {
      let active_index = 0;
      Array.from(document.querySelectorAll('ul > li')).forEach((item,index) => {
          if(item.classList.contains('active')) active_index = index;
      });
      return active_index;
   });

of course as mentioned by another answer , to get the desired effect on the items in the custom select list perhaps attach en EventListener.

so consider that the property "selectedIndex" has been defined on the parent element thus you could simply add Listeners which would update the parent.

[...document.querySelectorAll('ul > li')].forEach((item,index) => {
    item.addEventListener('click',evt => {
       item.parentNode.selectedIndex = index;
    });
});
like image 118
Saul does Code Avatar answered Oct 31 '22 15:10

Saul does Code