I'm writing a NiceGUI frontend for my Python code. This is my first time writing frontend, and I'm not very used to web-framework concepts. Essentially, the use of this frontend is to ask to user to insert the following variables (I know range is not a good variable name): variants_text: str keywords_text: str seed: int | None min_articles: int | None max_articles: int | None range: int | None limit: int | None This is the code I have written so far (the only dependecy is nicegui, and you need a dummy .txt file to pass Step1): from nicegui import ui class ArticleRetrieval: def __init__(self): self.page_title = "Article Retrieval" self.headers() self.stepper = ui.stepper().props("vertical").classes("w-full") self.step1_title = "Add input files" self.step2_title = "Add optional arguments" self.step3_title = "Retrieve articles" self.variants_uploaded = False self.variants_text = None self.keywords_uploaded = False self.keywords_text = None self.seed = None self.min_articles = None self.max_articles = None self.range = None self.limit = None self.positive_integer_validator = { "You can only insert a non-negative integer": self._acceptable_num } def _acceptable_num(self, n) -> bool: return (n is None) or (n == int(n) and n >=0) def _variants_uploaded(self, e): self.variants_uploaded = True self.variants_text = e.content.readlines() if self.keywords_uploaded is True: self.step1_next_button.visible = True def _keywords_uploaded(self, e): self.keywords_uploaded = True self.keywords_text = e.content.readlines() if self.variants_uploaded is True: self.step1_next_button.visible = True def _update_seed(self, e): self.seed = e.value self._step2_next_button_visibility() def _update_min_articles(self, e): self.min_articles = e.value self._step2_next_button_visibility() def _update_max_articles(self, e): self.max_articles = e.value self._step2_next_button_visibility() def _update_range(self, e): self.range = e.value self._step2_next_button_visibility() def _update_limit(self, e): self.limit = e.value self._step2_next_button_visibility() def _step2_next_button_visibility(self): if all( self._acceptable_num(x) for x in [ self.seed, self.min_articles, self.max_articles, self.max_articles, self.limit, ] ): self.step2_next_button.set_visibility(True) else: self.step2_next_button.set_visibility(False) def _ask_confirm(self): ui.markdown( f""" ##### DO YOU CONFIRM THIS DATA?<br> **variants**: {self.variants_text}<br> **keywords**: {self.keywords_text}<br> **seed**: {self.seed}<br> **min\\_articles**: {self.min_articles}<br> **max\\_articles**: {self.max_articles}<br> **range**: {self.range}<br> **limit**: {self.limit}<br> """ ) def headers(self): ui.page_title(self.page_title) ui.markdown(f"#{self.page_title}") def step1(self): with ui.step(self.step1_title): ui.upload( label="Variants (.txt file)", max_files=1, auto_upload=True, on_upload=self._variants_uploaded, ).props("accept=.txt").classes("max-w-full") ui.upload( label="Keywords (.txt file)", max_files=1, auto_upload=True, on_upload=self._keywords_uploaded, ).props("accept=.txt").classes("max-w-full") with ui.stepper_navigation(): self.step1_next_button = ui.button( "NEXT", icon="arrow_forward_ios", on_click=self.stepper.next ) self.step1_next_button.visible = False def step2(self): with ui.step(self.step2_title): ui.number( label="Seed", validation=self.positive_integer_validator, on_change=self._update_seed ).props("clearable") ui.number( label="Minimum articles", validation=self.positive_integer_validator, on_change=self._update_min_articles ).props("clearable") ui.number( label="Maximum articles", validation=self.positive_integer_validator, on_change=self._update_max_articles ).props("clearable") ui.number( label="Range", validation=self.positive_integer_validator, on_change=self._update_range ).props("clearable") ui.number( label="Limit", validation=self.positive_integer_validator, on_change=self._update_limit ).props("clearable") with ui.stepper_navigation(): self.step2_back_button = ui.button( "BACK", icon="arrow_back_ios", on_click=self.stepper.previous, ) self.step2_next_button = ui.button( "NEXT", icon="arrow_forward_ios", on_click=self.stepper.next ) self.step2_next_button.visibility = False def step3(self): with ui.step(self.step3_title): self._ask_confirm() with ui.stepper_navigation(): ui.button( "BACK", icon="arrow_back_ios", on_click=self.stepper.previous, ) ui.button( "RUN", icon="rocket_launch", on_click=lambda x: None # HERE I WILL PERFORM THE ACTUAL JOB ) def run(self): with self.stepper: self.step1() self.step2() self.step3() ui.run() ArticleRetrieval().run() My question is about the _ask_confirm method. It always prints the initial values of attributes, the ones I've defined in the __init__ method (i.e. all None). I would like that string to be updated every time I update values in Step1 and Step2. The thing I don't understand is that if, for example, I change the _update_seed method like this def _update_seed(self, e): print(self.seed) self.seed = e.value print(self.seed) self._step2_next_button_visibility() It prints the updated values. I hope someone can help me. Thank you very much. Continue reading...