dom-to-image icon indicating copy to clipboard operation
dom-to-image copied to clipboard

Checkbox and select Element values don't show their selected values

Open aarobc opened this issue 7 years ago • 5 comments

Use case: description, code

In a form, the <input =type="checkbox"/> and <select/> elements don't show the selected values.

Change the selected check boxes, and select in the dropdown, then click the Test Button in the demo to see the behavior codepen

Expected behavior

The rendered image would display the selected form elements

Actual behavior (stack traces, console logs etc)

Whatever the elements loaded with are displayed

Library version

2.5.2

Browsers

  • [ x] Chrome 49+
  • [x ] Firefox 45+

aarobc avatar Apr 13 '17 23:04 aarobc

Please fix this.

rohithconceptowl avatar Apr 19 '17 07:04 rohithconceptowl

I have a hacky workaround for this if any one is interested. It seems to be rendering an element based on its attributes but not its properties. My workaround is to update an element's attribute to match its property before it's rendered using the filter function:

domtoimage.toPng(ment,{
    filter:function(node){
      if(node.nodeType===1 && node.tagName==="INPUT" &&
         (""+node.type).toLowerCase() === "checkbox"){ 
        if(node.checked){
          node.setAttribute('checked', true);
        }else{
          node.removeAttribute('checked');
        }
      }
      return true;
    }
  })

http://codepen.io/anon/pen/ZKXogq?editors=1111

Works for checkboxes and I assume for selects too.

JoolsCaesar avatar May 05 '17 13:05 JoolsCaesar

@JoolsCaesar could you give an example on how to do this for select lists?

nattu1989 avatar Mar 28 '18 07:03 nattu1989

@nattu1989, there's a working example in the codepen

       else if(node.tagName==="SELECT" && node.selectedIdx!=-1){
          var options = node.childNodes; // Assumption!
          var optionCount = 0;
          var selectedIdx = node.selectedIndex;
          for(var i=0; i<options.length; i++){
            var option = options[i]; // Maybe not an option
            if(option.tagName==="OPTION"){
              if(optionCount === selectedIdx)
              {
                options[i].setAttribute('selected', true);
              }
              else
              {
                options[i].removeAttribute('selected');
              }
              optionCount++;
            }
          }
        }

If you're only doing it for select elements, change that else if to and if and bung a node.nodeType===1 && at the front of the condition. You could probably tidy up that indexing stuff as well with getElementsByTagName. Something like (untested!):

if(node.nodeType===1 && node.tagName==='SELECT' ){
   var options = node.getElementsByTagName('OPTION'); 
   var selectedIdx = node.selectedIndex;
   for(var i=0; i<options.length; i++){
      if(i === selectedIdx){
         options[i].setAttribute('selected', true);
      }else{
         options[i].removeAttribute('selected');
      }
   }
}

JoolsCaesar avatar Apr 17 '18 13:04 JoolsCaesar

Similar to other comment I do as follow for select elements using React:

ref.current.querySelectorAll('option').forEach(option => {
  if (option.selected) {
    option.setAttribute('selected', 'selected')
  } else {
    option.removeAttribute('selected')
  }
})

rmariuzzo avatar Dec 07 '21 15:12 rmariuzzo