Does a backdraft component have any visibility into the dom element where it's being inserted?

43 Views Asked by At

Using backdraftjs I want to do a customized fancy select widget similar to chosen.js.

My thought was that I could have markup like this:

<div id="bobSelect">
     <select name="bob">
          <option>Bob Crane</option>
          <option>Bob Hope</option>
          <option>Bob Melvin</option>
          <option>Bob Dobbs</option>
      </select>
</div>

Then I'd replace it via something like

render(FancySelectComponent, {}, 'bobSelect', 'replace');

...and in FancySelectComponent I would grab things like the options from bobSelect.

However it looks like there's no way for FancySelectComponent to have visibility into the dom element where it will eventually be inserted. Is that right?

So instead maybe in render I need to do something like

render(FancySelectComponent, {basedOn: 'bobSelect'}, 'bobSelect', 'replace');

Does that make sense?

1

There are 1 best solutions below

0
On BEST ANSWER

You are correct; as written,

render(FancySelectComponent, {}, 'bobSelect', 'replace');

FancySelectComponent's constructor is not provided any information about the existing DOM tree rooted at div#bobSelect. In fact, the render application above is just syntax sugar for...

let result = new FancySelectComponent({});
let replacedNode = document.getElementById('bobSelect');
let parentNode = replacedNode.parentNode;
parentNode.removeChild(replacedNode);
parentNode.appendChild(result.render());
return result;

(note: in your example, both the replaced and replacing node are single nodes, but render can handle cases when either or both are a forrest of nodes)

You are also correct that, if you want access to the existing div#bobSelect, then you can pass it directly to the constructor via the second argument to render:

render(
  FancySelectComponent, 
  {replacingDiv:document.getElementById('bobSelect')}, 
  'bobSelect', 
  'replace'
);