Add name argument to add_component

Please add the name argument to the add_component function.

The first example on the documentation of add_component would be xyp.add_component(lbl, x=10, y=10, name='hello_label') and it could be reached with xyp.hello_label.

FR inspired here by @alcampopiano.

4 Likes

Hi Stefano,

When you drag and drop components onto your Form in the visual designer, components are set as attributes on the Form object. The purpose of component naming is to let you refer to these components as attributes on your Form object (e.g self.hello_label).

This isnā€™t necessary when you create components in code (such as lbl in your example), as itā€™s straightforward to set the attributes yourself:

xyp.add_component(lbl, x=10, y=10)
self.hello_label = lbl
1 Like

Thanks very much Bridget.

I often use add_component in a loop. In those cases, I may want to give my components ā€œnamesā€ dynamically based on a list.

I can use setattr to accomplish this. Do you see any problems with this approach?

For example:

names=['a', 'b', 'c']

for n in names:
  
  l=Link(text=n)
  setattr(self, n, l) # assigning a new property based on a string
  self.add_component(l)


# referencing by custom name
print(self.c.text) 

# returns 
'c'

The other thing is that, in a previous post, Ian mentioned that it was not a great idea to add arbitrary attributes onto a component (e.g., self.my_button.name='foo'). Instead, he recommended to use the tag property to store attributes.

Is it still recommended to use the tag property to store arbitrary attributes on components?

Hi Al,

Thanks for the example and yes, youā€™re exactly right - the recommended approach would be to use the tag property to store attributes on components:

names=['a', 'b', 'c']

self.tag = {'my_extra_components':{}}

for n in names:
  l=Link(text=n)
  self.tag['my_extra_components'][n] = l
  self.add_component(l)

print(self.tag['my_extra_components']['c'].text) # prints 'c'

And for my example above:

xyp = XYPanel(width=400, height=400)
self.add_component(xyp)
lbl = Label(text='I am a label')
xyp.add_component(lbl, x=10, y=10)
self.tag['hello_label'] = lbl
    
print(self.tag['hello_label'].text) # prints 'I am a label'
3 Likes

Thanks very much for the helpful clarification Bridget.

2 Likes

Hi Bridget,

I would like a clarification on the clarification: is it always a bad idea to add arbitrary attributes to any component, including forms, or forms are an exception to the rule?

In my forms I often fill the __init__ with self.something = something. I just cloned a few apps from the blog page and I see the same pattern.

1 Like

bringing up this thread again - clarification on the clarificationā€¦

Is it the recommended approach because name_conflicts or another reasonā€¦

I see the tag component as super useful and a convenient place for certain things.
Especially for components that are not a Form which is when I tend to use it mostā€¦

But for a Form I donā€™t typically use it because it rarely seems pythonic to me.
(apart from when it does :thinking: )
I think your initial post @bridget, to me, seems the preferred way to do something like thatā€¦

in this post from a few years ago @ian mentions the phasing out of directly adding attributes to components. Also linked above
But like @stefano.menci mentions its also used for most tutorials and in most situations seems like the best approachā€¦

"Safe" names for developer-defined object members - #2

Is there a distinction here between components that may have something like this phased outā€¦
Surely the Form will never have this phased out since itā€™s a python class with a __dict__

Hi @stefano.menci, @stucork,

Itā€™s perfectly fine (and often very useful!) to add arbitrary attributes to Forms. For components, the recommended approach is to use the tag property, to avoid name conflicts, as @stucork points out.

3 Likes