Adding custom component

Hello, I have a form ‘Keyboard’ with a text box ‘proposition__wrt’, and I have a custom component which is a form with a button, when the button is clicked I wish it to add to the text of the text box ‘hello world’.
This is what I tried but when I click the button it does nothing:

  def button_1_click(self, **event_args):

    Keyboard_instance=Keyboard()

    Keyboard_instance.proposition__wrt.text+='Hello World'

Thanks in advance for the help

1 Like

Your click event handler creates a brand new instance of the form and sets its text. That instance is not visible because it’s never added to any container and gets destroyed when it gets out of scope (when the event handler functions ends).

There are two ways to do your job: create a property on the custom component so you can tell what text box to update, or define a button_clicked custom event in the custom component, fire the event when the button is clicked, then in the main form define the custom_component_1_button_clicked event handler to set the text.

In both cases the custom component is a closed box: it doesn’t see what’s outside itself. It only sees its properties (and if you assign a text box to a property, then it sees the text box) and can trigger its own events (kind of a middle man between the events of its own components and its containers).

I’m on my cell and can’t type example code now. I hope this is enough to put you on the right path. If it is not, ask for clarifications and I’ll try to go deeper.

3 Likes

Hello, I could not really make it work
here’s what I tried:

I added helloworld as custom event in the main form, then

#in custom component
from ..MainForm import MainForm
  def button_1_click(self, **event_args):
    """This method is called when the button is clicked"""
    MainForm.raise_event('x-helloworld')

#in main form
#under init method
self.add_event_handler('x-helloworld',self.handle_helloworld)

#as a method
def handle_helloworld(self,**event_args):
   self.proposition__wrt.text='hello world'

i get the error TypeError: raise_event() takes exactly 2 arguments (1 given)

1 Like

You are trying with custom events, the one with x-. Those are useful across components, not with custom components.

Instead you should try with events for custom components. Search for the word “custom event” in this page: Anvil Docs | Custom Components

1 Like

Indeed I’m having problem exactly across components.
I already have gone throught that documentation and id does not provide a straightforward answer.

Consider I also have added a button in the main form which triggers the exact same ‘x-helloworld’ event and it works perfectly.

Def buttonInMainPage_click(self):
Self.raise_event(‘x-helloworld’)

My issue is that I cannot get the button in custom_component to trigger the ‘x-helloworld’ event.
The only difference is
MainPage.raise_event(…) in custom component versus
Self.raise_event(…) in MainPage, the rest is exactly the same. Why does it not work?

Could you please edit my code? Thanks

1 Like

Custom components are forms with their own components and are seen by the main form as one single component. The main form doesn’t see the code inside the custom component and the custom component doesn’t see the content of the main form.

If you want a custom component to tell the main form that something is happening inside the custom component, then you need to define an event. A real (custom) component event, not an x-... custom event managed with add_event_handler.

If you want the main form to expose something to a custom component, you need to create a property on the custom component and set that property from the form (or in some cases the IDE), so the custom component can work with its own properties.

If you are having problems across “components” rather than across “custom components”, then you may need to use custom events, named x-... and managed with add_event_handler.

Well… maybe yes, but I don’t see your code.
I could have a look at it if you share a clone link.


Please pay attention to the formatting on your posts. Python code without indentation is difficult to read. Here are a few tips: How to ask a good question

2 Likes

Hello, it finally worked with custom event method. thanks for the help.
I was wondering if you could expand a little on the property method you mentioned in your first answer. You said I could set a property in the cutom component so to tell it which text box to update. I tried to set a property ‘formprop’ of type ‘form’ in the custom component, pass in ‘MainPage’ as default value, and then update the text box in MainPage in the following way:

#in custom component, in button_1_click
self.formprop.text_box_1.text=‘hello world’

but I get an error, saying that ‘str’ type has no attribute ‘text_box_1’: it sems the form type property is actually a string and not a form, which makes me wonder how to make use of it in this case.
How would you proceed? thank you

This means that the formprop property has been assigned a string, not a form.

You cannot assign (as far as I know) a form instance to the custom component at design time, you need to assign it at run time. The right place to do it is in the __init__, after the self.init_components(**properties) (because if you do it before, the custom component doesn’t exist yet).

# this assigns a string to the property
self.custom_component.formprop = 'Form1'

# this assigns a form to the property (assuming the 
# code runs in a method of the form class)
self.custom_component.formprop = self

EDIT
With this approach your custom component knows the name of the texbox, which leads to two problems:

  • the form that uses that custom component must have a textbox named text_box_1
  • if the form has more than one instance of that custom component, they all will interact with the same text box.

A better way would be to assign the text box rather than the form:

# in the form
self.custom_component.status_text_box = self.text_box_1

# in the custom component
self.status_text_box.text = 'hello world'
2 Likes

Now it is all clear, thank you very much