How to refer to a div in custom html from python and vice-versa

P.S.

I figure you probably also want to work out when a component has changed position in python this is possible… but requires more leg work… I’ve had a play around and here’s some additional code that will make this happen:
https://anvil.works/build#clone:6IRFB67BBM6WJTS6=XFHHHJKQDMEG56OCJ7HBBC6U

The pseudo code is as follows:

  • add the anvil components to the left/right slots as before
  • add the anvil components to a javascript array
  • use the dragula on drop event listener which provides the element, target, source and sibling.
  • use the javascript array to get the anvil component that was dropped, and the sibling component
  • use anvil.call to send these back to python

Javascript in addition to the previous code


drake = dragula([document.querySelector('#left'), document.querySelector('#right')]);
  
drake.on('drop', function(element, target, source, sibling){
  const anvil_component = get_component(element);
  const anvil_sibling = get_component(sibling);
  anvil.call(element, 'dropped', anvil_component, target.id, source.id, anvil_sibling);
});

var components = [];

function get_component(parent) {
  if (parent === null){
    return
  }
  for(i=0; i<components.length; i++){
    if (components[i]._anvil.element[0] == parent.firstElementChild){
    return components[i];
    }
  }
};
  
function add_component(component) {
    components.push(component.v)
  };


Python code

class DragulaForm(DragulaFormTemplate):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)

    # Any code you write here will run when the form opens.
    self.left_components = []
    self.right_components = []
    self.slots = {'left': self.left_components, 'right': self.right_components}
    
    # left components add dynamically
    for i in range(10):
      component = Button(text=f'button_{i}', role='raised')
      self.left_components.append(component)
      self.add_component(component, slot='left')

    # right components add dynamically
    for i in range(10, 20):
      component = Button(text=f'button_{i}', role='raised')
      self.right_components.append(component)
      self.add_component(component, slot='right')
      
    print(f"{'element':9} | {'from':5} | {'to':5} | {'at_index'}")
    print("="*36)
      

  def dropped(self, element, slot_to, slot_from, sibling):
    self.slots[slot_from].remove(element)
    
    for i, sib in enumerate(self.slots[slot_to]):
      if sib is sibling:
        break
    else: # it was added after the last element so no sibling... 
      i+=1
    self.slots[slot_to] = self.slots[slot_to][:i] + [element] + self.slots[slot_to][i:]
    print(f"{element.text:9} | {slot_from:5} | {slot_to:5} | {i}")


  def form_show(self, **event_args):
    """This method is called when the HTML panel is shown on the screen"""
    from itertools import chain
    for component in chain(self.left_components, self.right_components):
      self.call_js('add_component', component)
  

managed to get itertools in there :wink:


In Action

7 Likes