Want to be able to generate x number of TextBoxes

I want to be able to generate a certain number of text boxes depending on a number declared by another text box. In this case trav = 5, so I want to show 5 boxes

This is where I have got so far, where trav is the variable that I ultimately want to be a textbox variable.

    self.text_box = {}
    gp = GridPanel()
    trav = 5
    i = 1
    i += i
    while i >= trav:
      self.text_box = TextBox(text=i,
                          font ="Consolas",
                          bold= True,
                          foreground="#FFF",
                          background="#999",
                        )
    self.text_box[i].tag.name = i
    self.text_box[i].role = "text"
    gp.add_component(self.text_box[i], row=1, col_xs=3, width_xs=1)
    self.add_component(gp)

At the moment I am getting a key error. I presume I need to do something with i, to increment the label name but I cant get it to work.

Thanks in advance

When posting, try to include a specific reference to the line which is throwing the error. However, I’m guessing it’s when referencing self.text_box[i].

You are redeclaring that variable when you declare it to be a TextBox having first declared it as a dictionary. From that point it cannot have an index.

There are a few issues with the code, such as the while loop will never run as variable i is initialised with a lower value than trav, which you then test to see if it is greater than or equal to trav (which is won’t be).

Here’s a suggested alternative to you code (untested and from memory so it might not be perfect) :

self.text_box = []
gp = GridPanel()
trav = 5
for i in range(1, trav):
  tb = TextBox( font=... etc. )
  tb.role = "text"
  tb.tag.name = i
  gp.add_component(tb, .....)

# You might want to add `gp` to a container instead of just to `self`.
self.add_component(gp)

The indenting is important as well.

Does that help you at all?

Thank you David, yes you are right I did mean that.

It works!!! And it is perfect.

1 Like

I have now set up an on change event on another field, so the user enters the value of the variable, it works great the first time, but if you change the number again, it adds another load of boxes.

I’ve seen the clear() statement on the docs, to just get rid of everything and presume this will need to go at the start of the onchange event.

I’ve tried doing tb.clear() and gp.clear() but its not working, any help would be appreciated.

Here is the amended code

  def text_box_how_many_change(self, **event_args):
        
        self.text_box = []
        gp = GridPanel()
        trav = int(self.text_box_how_many.text)
        trav = trav + 1
        for i in range(1, trav):
          if i<=4:
            row ='A'
          elif 5<= i<8:
            row ='B'
          elif 9<= i<12:
            row ='C'
          else:
            row ='D'
          tb = TextBox(text=(f"  enter traveller {i}'s age"), font ="Source Sans Pro", bold= True,foreground="#FFF",background="#999",)
          tb.role = "text"
          tb.tag.name = i
          gp.add_component(tb, row=row, col_xs=3, width_xs=2)
        self.add_component(gp)
        pass

Without seeing it all I can only be general -

Firstly, move the GridPanel creation to the init method of your form, and assign it to self.gp so you can reference it everywhere.

Then you can add it by doing self.add_component(self.gp) and in your change event, clear the grid panel by self.gp.clear()

But - maybe you don’t want to do this in the change event of a text box. I’m not 100% sure when that event fires, but it could be on keypresses (I’ve not checked the docs). If so, it may fire when you’re half way through entering a multidigit value such as 10.

Probably better to either process the value on the enter_pressed event or have a “go” button next to the text box.

3 Likes

Thanks for the advice, there isnt much to see anyway at the moment, as I’m still just trying to figure out the best method of achieving a result, its a quotation form where most entries are just single boxes, but this one, how many travellers there are, is a variable that will affect the quote since the ages of each traveller are rated differently.

So at the moment all I have is one textbox on a page, that the entered result, say 4 for example, becomes the trav variable result.

She’s created the whole process on an Idle Terminal, but its translating that to Anvil as a GUI. So, Im looking to replace all the inputs on the Idle Terminal with boxes. I’d like to style it as a window in the page with boxes on the right as the inputs and the left as the questions but before I get to any of that I want to get the questions working on a basic form, the rest are all done on another app and I just put this one on a separate test app, because it has variable boxes.

I really dont know python, but its a project for my daughter and I’m really just looking to help her get started in the right direction, which is why I though Anvil was good, since she can drag and drop elements, without having to have learned how to create and style them. I know HTML, SQL and CSS very well, plus a bit of PHP and JQuery, though my work has been limited to my own websites and mostly reading and amending others PHP and JQuery, rather than creating my own.

Anyway, thank you for taking time to reply to me, it truly is appreciated! As I explained to my other half, to me, this is like trying to drive a Ferrari when you haven’t even passed your test.

Mostly I just sit here with a blank expression on my face, not knowing where to start :slight_smile:

David, once again you are a superstar!!! Solved it! Also you were right about the onchange, as soon as the entry is changed it fires, not after you press enter.

So, to solve this I separated the onchange with the gp.clear() in it, then moved the rest of the function into and on pressed enter event.

Now it works perfectly.

1 Like