# Configuration File Upload

**URL:** <https://forum.inductiveautomation.com/t/configuration-file-upload/45526>\
**Category:** Module Development\
**Created:** [April 13, 2021, 11:44am UTC](https://forum.inductiveautomation.com/t/configuration-file-upload/45526 "2021-04-13T11:44:54Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sam1](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@sam1](https://forum.inductiveautomation.com/u/sam1)\
**Post date:** [April 13, 2021, 11:44am UTC](https://forum.inductiveautomation.com/t/configuration-file-upload/45526/1 "2021-04-13T11:44:54Z")

</div>

Hi All,

I'm in the process of adding a file upload field to my device driver configuration. Is it still the case that a custom record edit page must be implemented as described below? Or is the only alternative to implement the depreciated classes used in the modbus example?

> [@AbstractDriver Module - StringField for password input](http://forum.inductiveautomation.com/t/abstractdriver-module-stringfield-for-password-input/16238):
>
> In an AbstractDriver Module, I would like to add some property for an password input field. I don’t find the property or flags to add in order the StringField is displayed in password style password : \*\*\*\*\* public static final StringField PASS = new StringField(META, "MyPass", SFieldFlags.SMANDATORY);

Also, I've found that when I try to add additional links by overriding getLinks() (as previously shown in the ModbusTcpDriverType example using DriverType) I receive an error that function does not exist within the DeviceType class. I'm guessing this has changed since DeviceType was introduced. Is there an alternative available?

As always, any help is greatly appreciated - thanks.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [April 13, 2021, 12:51pm UTC](https://forum.inductiveautomation.com/t/configuration-file-upload/45526/2 "2021-04-13T12:51:51Z")

</div>

You can still add custom actions to your record instance by overriding `addRecordInstanceActions` in `DeviceType`.

The following code is Kotlin instead of Java so you’ll just have to squint and get the idea instead of copy it. This is used by the FINS driver to lead to a custom tag editing Wicket panel.

```auto
    override fun addRecordInstanceActions(
        view: RepeatingView?,
        configPage: IConfigPage?,
        parentPanel: ConfigPanel?,
        mainRecord: PersistentRecord?,
        subRecord: PersistentRecord?
    ) {

        super.addRecordInstanceActions(view, configPage, parentPanel, mainRecord, subRecord)

        if (subRecord != null) {
            view?.add(
                ConfigureTagsInstanceAction(
                    view.newChildId(),
                    configPage,
                    parentPanel,
                    mainRecord as DeviceSettingsRecord
                )
            )
        }
    }

    class ConfigureTagsInstanceAction(
        id: String,
        configPage: IConfigPage?,
        parentPanel: ConfigPanel?,
        record: DeviceSettingsRecord
    ) : AbstractRecordInstanceAction<DeviceSettingsRecord>(
        id,
        configPage,
        parentPanel,
        record
    ) {
        
        override fun getLabel(): IModel<*> {
            return Model.of("addresses")
        }

        override fun getCssClass(): String {
            return "config"
        }

        override fun createPanel(record: DeviceSettingsRecord?): ConfigPanel {
            return FinsAddressConfigPanel(id, configPage, parentPanel, record)
        }
    }

```

---

<div class="post-metadata">

**Author:** ![sam1](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@sam1](https://forum.inductiveautomation.com/u/sam1)\
**Post date:** [May 5, 2021, 5:00am UTC](https://forum.inductiveautomation.com/t/configuration-file-upload/45526/3 "2021-05-05T05:00:56Z")

</div>

Thanks a lot Kevin. I’ve been able to use the above code to create a custom action which links to a settings page.

My current problem is when the link to the new page is clicked no content is displayed and there are no errors in the logs. I’ve reduced the page content down to a header and a single label without result.

An interesting thing I’ve noticed is that it seems the getTitleModel() function is never actually called (I’ve inserted a logged which is never printed), however the following logger.info("Title area: "+isTitleVisible()); returns true.

I was hoping someone could shed some light on what I’m doing wrong. I’ve included the code below for reference.

Note: all 3 files are in the same directory.

The .properties file:

```auto
configurationtitle=Address Upload
label=This is a new label

```

The .html file:

```auto
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:wicket="http://wicket.sourceforge.net/">
	<body>
		<wicket:panel>	
			<form wicket:id="form">
				<div>
					<span wicket:id="form-label">Message</span>
				</div>
			</form>
		</wicket:panel>
	</body>
</html>

```

The .java file:

```auto
public class FileUploadUI extends ConfigPanel {
	
    private final Logger logger = LoggerFactory.getLogger(getClass());

	private final IConfigPage configPage;
	private final ConfigPanel returnPanel;
	private final PersistentRecord record;

	public FileUploadUI(String id, IConfigPage configPage, ConfigPanel parentPanel, PersistentRecord record) {
		
		this.record = record;
		this.configPage = configPage;
		this.returnPanel = parentPanel;

		logger.info("Adding components");
		logger.info("Title area: "+isTitleVisible());

		final Form<Object> form = new Form<Object>("form");

		form.add(new Label("form-label", new LenientResourceModel("FileUploadUI.label")));

		add(form);
		
	}

	@Override
	public String[] getMenuPath() {
		return new String[0];
	}

	@Override
	public IModel<String> getTitleModel() {
		
		logger.info("Creating title");
		return new LenientResourceModel("FileUploadUI.configurationtitle");
	}
}

```
