# Dynamic forms > This module can reused to render dynamic forms returned by the TransferWise for Banks API. > Note that while all code is fully tested and has a simple, generic API, the interface needs more polish to distribute it as a Maven artifact (e.g. thread safety, review contracts,...).
## About Some endpoints in the TransferWise API return a dynamic UI that needs to be rendered to the user. These endpoints are: - [Recipient account requirements](https://transferwise.github.io/api-docs-banks/#recipient-accounts-requirements), used to get the necessary fields to create a new recipient. - [Transfer requirements](https://transferwise.github.io/api-docs-banks/#transfers-requirements), needed to get the necessary fields to complete a transfer. Rendering such a dynamic UI is quite challenging and therefore, the reference implementation contains a separate module dynamicforms that handles all that complexity for you. ## Advantages When using the `dynamicforms` module, the following problems are solved for you: - Shows several sections as separate UI tabs - Renders text input fields with local error validations (min/max length, regex,... ) - Renders selection inputs with refreshes of the form (e.g. choosing the USA as the country adds a "state" input field to the form) - Summarizes the current form state into either InComplete, ValidationError or Complete - Allows to add static components on top of the dynamic ones - Processes the form output to collections that can be sent back to the backend ## Key classes The main classes involved in displaying a dynamic form UI are: - `DynamicFormView`: can be included in XML to render a dynamic form - `DynamicFormController`: main interface with the dynamic form component. Allows to show the form, exposes the current `DynamicFormState` and allows to get the processed form input. - `DynamicFormsWebservice`: tells the `DynamicFormController` how to load and refresh the form for the current endpoint - `DynamicFormState`: indicates whether the form is `Loading`, `InComplete`, `ValidationError` or `Complete` - `StaticFormGenerator`: allows displaying static content on top of the dynamic content ## Getting started In order to integrate a dynamic form into a new screen: 1. Include a `DynamicFormView` into your `layout.xml`. ```xml ``` 2. Implement a `DynamicFormsWebService` and implement `getForm()`and `refreshForm()`. ```kotlin interface DynamicFormsWebService { suspend fun getForm(): List suspend fun refreshForm(attributes: Map, details: Map): List } ``` 3. Get the `DynamicFormController` from the `DynamicFormView` and call `showForm()` on it. As the `DynamicFromController` actually does network requests in the background, it needs a `CoroutineScope` to properly clean up its resources. (typically the [viewModelScope](https://developer.android.com/topic/libraries/architecture/coroutines#viewmodelscope)) ```kotlin val dynamicForm = view.findViewById(R.id.dynamic_form) dynamicForm.controller.showForm(scope = myCoroutineScope, dynamicWebService = MyDynamicFormsWebService()) ``` 4. Subscribe to the `DynamicFormController` `uiState` to get updates about the status of the form. Notice how the subscription needs to be done within a `CoroutineScope` to avoid leaking any subscriptions. (typically the [viewModelScope](https://developer.android.com/topic/libraries/architecture/coroutines#viewmodelscope)) ```kotlin myCoroutineScope.launch { dynamicFormController.uiState.consumeEach { dynamicFormState -> when (dynamicFormState) { is Loading -> TODO() is DynamicFormState.Incomplete -> TODO() is DynamicFormState.ValidationError -> TODO() is Complete -> TODO() } } } ``` 5. Get the `currentAttributes()` and `currentDetails()` from the `DynamicFormController` to process the form input. ```kotlin val attributes: Map = dynamicFormController.currentAttributes() val details: Map = dynamicFormController.currentDetails() ``` 6. Specify theme attributes for the dynamic form elements in your `styles.xml` to ensure they form looks as expected. ```xml ``` ```xml