Focus on new textbox in repeating panel (todo list)

I am making simple ToDo app and I am adding new task pressing enter or pushing “plus” button. It makes new row with textbox, checkbutton and other fields but with no data (like in Google Tasks in Gmail).

I would then like to get the new textbox focused after refresh, is it possible ?

  def btn_add_task(self, **event_args):
    """This method is called when the button is clicked"""
    anvil.server.call('add_task')
    self.refresh()

I can not figure out how to address that new row to make it focused so if you for example press enter, you could be writing another task right away.

You can call the TextBox’s focus() method to set the focus on it after you create it. You need to do this in the currently-open Form, so you need to get the last element of the Repeating Panel like this:

    self.repeating_panel_1.get_components()[-1].text_box_1.focus()

Here’s an app that does that:

https://anvil.works/build#clone:H2344QSUZIS7ACIO=R7RFIPBWBVCYXJ6RRAJRMDLY

2 Likes

yes it works !

Just one more thing. I am trying to put it work with Enter also, but with no success. I still have not clear how to refresh parent from template.

So for now I just use this, which works:

self.parent.items = anvil.server.call(‘get_data’)

but not in this case.

I tried to follow your instructions in this thread: Repeating panel to collect new information? - #5 by thenerdypython but it didn’t work for me either.

If you could add it in this example it would be just great.

Thank you.

The most robust way to run the refresh method (or any other method) on the top-level Form is to create an event handler on that Form and raise the event from the template.

Creating the event handler:

class Form1(Form1Template):

  def __init__(self, **properties):
    # ...
    self.set_event_handler('x-refresh', self.refresh)
    
  def refresh(self, **event_args):
    #...

Raising the event:

class ItemTemplate1(ItemTemplate1Template):
  #...

  def button_1_click(self, **event_args):
    get_open_form().raise_event('x-refresh')

That way, if the ItemTemplate is used by a different Form that doesn’t have a refresh method, the x-refresh event will be raised and ignored rather than causing an exception (it’s the Publish-Subscribe pattern which is meant to achieve loose coupling between components).

I’ve modified my example app to have a ‘refresh’ button on each row that runs the refresh() method of the main Form.

https://anvil.works/build#clone:H2344QSUZIS7ACIO=R7RFIPBWBVCYXJ6RRAJRMDLY

2 Likes

thanks for explanation, I got it now. Just one more question.

It works only if the form is Startup form, if is it another form, it just don’t get to the refresh.

I am trying to do this on Todo form, which is not startup form. When I change it to startup form it works, if I change it back it doesn’t.

image

If you’re using get_open_form().raise_event('x-refresh'), the x-refresh event will get raised on the open Form. The open Form needs to have an x-refresh event registered in order for something to happen. Have you got an x-refresh event set on your Todo Form?

yes I have, maybe I am doing something wrong in other part.

I added another form to your sample app and as soon as I set it up as the start form, it doesn’t work either. Only “plus” works because it is on the parent.

Here is your sample app with Form2 added:

https://anvil.works/build#clone:V7NJBKOYAS5IES74=YTP5XPLZ7EJMO6BKRGZ7CJJJ

Your open form is the default form (Form2) which has no event handler.
You are adding the other form as a component.

So what you are doing is opening the default form (Form2).
The button adds Form1 as a subform to Form2.
Form1 has the event handler.
ItemTemplate1 does get_open_form().raise_event('x-refresh') which attempts to raise an event on the open form (Form2) which has no handler.

If you need to reference a subform on the open form you may need to store it in a property. Eg in Form2 :

  def button_1_click(self, **event_args):
    
     """This method is called when the link is clicked"""
     f = Form1()
     self.subform = f 
     self.content_panel.clear()
     self.content_panel.add_component(f)

then you can do

get_open_form().subform.raise_event......

Does that make sense?

2 Likes

finally, it works ! :smile:

I don’t really need to add it as component, it was my error, I just changed it to:

 f = Form1()
 open_form(f)

and it works.

thank you

P.S. I have also tried the version with form as component and subform refresh, and it also works, now I understand perfeclty, I have learned a lot with this example, thanks again.

3 Likes