# Ignition Settings Next Page

**URL:** <https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595>\
**Category:** Module Development\
**Created:** [September 11, 2020, 1:09pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595 "2020-09-11T13:09:42Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 11, 2020, 1:09pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/1 "2020-09-11T13:09:42Z")

</div>

Hello,

In the OPC device settings there is a table with different devices, and then once you select that device and click next it pulls up a settings record different from the others.

This looks like a recordActionTable, but how do I get the ‘next’ intermediary step so that I could have a panel for multiple different settings types?

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/1/115d59b0f26d9a9ed80cdf080f02bf5dce5d9c3c.png)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 11, 2020, 1:49pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/2 "2020-09-11T13:49:50Z")

</div>

You have to supply one or more DriverType instances in your module hook. The DriverType instances supply the information needed to show up in that list of drivers, and provide all of the information needed for the OPC Server to offer the correct settings record combination, and then to instantiate your driver with such a record.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 11, 2020, 1:52pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/3 "2020-09-11T13:52:27Z")

</div>

@pturmel In my application I want to create the settings list itself, but I am not actually creating drivers here. I basically want to recreate how that settings workflow works, but not for drivers.

Example: User selects create new Fleet

a list of fleet types is shown with check boxes (like that above)

User selects a fleet and clicks next,

A specific settings record for that fleet is pulled up.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 11, 2020, 2:33pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/4 "2020-09-11T14:33:29Z")

</div>

Ok. Well, the first thing will be supplying an IConfigTab via your GatewayHook’s .getConfigPanels() method. The config tab will show up in the ConfigCategory it names, using the translatable menu entry given. Use DefaultConfigTab.builder() to handle the details.

Your IConfigTab instance must override .getPanel() to actually deliver a configuration page. This first page would be a subclass of ConfigPanel that presents your bullet list. No settings record, just programmatically placed wicket form elements. Your onSubmit() method would examine the radio buttons and select the next ConfigPanel to display.

You’re going to have to get comfortable with wicket. /:

Or have your first ConfigPanel deliver a React app. (:

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 11, 2020, 3:01pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/5 "2020-09-11T15:01:47Z")

</div>

It’s more specific than your needs, but check out `com.inductiveautomation.ignition.gateway.web.components.RemoteConfigItemChoicePanel` for a relatively simple starting point.

To use it, have your ExtensionPointType implementation (should probably extend BaseExtensionPointType) return that new panel, then the callback for the panel will actually edit your records. In this case, there’s actually two steps in the “wizard” - first, the remote gateway is selected, then that remote gateway selection brings up the choice of remote providers powered by the RemoteConfigItemChoicePanel.

```auto
    @Override
    public ConfigPanel newRecordConfigPanel(PersistentRecord[] records, IConfigPage configPage,
                                            ConfigPanel parentPanel) {
        super.newRecordConfigPanel(records, configPage, parentPanel);
        return new RemoteGatewayChoicePanel(...) {
            @Override
            protected void onGatewaySelected(ServerId gateway) {
                configPage.setConfigPanel(...));
            }
        };
    }

```

---

<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:** [September 11, 2020, 3:07pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/6 "2020-09-11T15:07:40Z")

</div>

The device page workflow uses `com.inductiveautomation.ignition.gateway.web.components.ExtensionPointPage`. It takes care of everything you’re seeing, but you do have to start using `ExtensionPointType` to model your thing and the types of sub-things that exist.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 11, 2020, 3:33pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/7 "2020-09-11T15:33:16Z")

</div>

@Kevin.Herron @pturmel @paul-griffith Looks like I’ve got some programming to do, as always thank you for the quick responses.

I will see what I can come up with.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 21, 2020, 4:59pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/8 "2020-09-21T16:59:13Z")

</div>

Hi Kevin,

Do you have any examples of ExtensionPointType/ExtensionPointPage being used?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 21, 2020, 5:38pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/9 "2020-09-21T17:38:13Z")

</div>

> **[inductiveautomation/ignition-sdk-examples](https://github.com/inductiveautomation/ignition-sdk-examples/tree/master/slack-alarm-notification/slack-notification-gateway/src/main/java/com/inductiveautomation/ignition/examples/slack/profile)**
>
> master/slack-alarm-notification/slack-notification-gateway/src/main/java/com/inductiveautomation/ignition/examples/slack/profile

Check the Slack example; it extends the Alarm Notification system’s extension point.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 21, 2020, 5:38pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/10 "2020-09-21T17:38:58Z")

</div>

Thanks I’ll check it out!

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 24, 2020, 6:21pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/11 "2020-09-24T18:21:25Z")

</div>

> [@paul-griffith](#):
>
> com.inductiveautomation.ignition.gateway.web.components.RemoteConfigItemChoicePanel

Hey sorry to keep asking so many questions. I keep re reading the javadocs trying to understand how to implement the ExtentionPointPage and ExtensionPointType. I cannot figure it out, and the slack example also didn't really help ,e understand unfortunately.

I gave a feeble attempt at writing some code for ExtensionPointPage. The javadoc does not document what getExtensionPointManager() does.

Heres my attempt:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/8/2811cf0435a9cc8ad56f89481f0cfe3e61d73f9c.png)

And heres my type.. which I do not know where/how it connects to anything. Is the type supposed to be something specific? Am I supposed to make a persistentRecord for each ExtensionPointType? I am so lost.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/4/e41ca22fddd87783291baa7fb44966b969547acc.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 24, 2020, 6:45pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/12 "2020-09-24T18:45:25Z")

</div>

Okay, so your ExtensionPointManager needs to be implemented. That should be the (effectively singleton) ‘manager’ that book-keeps all the individual instances you’re going to create.  
That interface has two methods that align pretty well with a backing map -  
`ExtensionPointType getExtensionPoint(String typeId);`  
`List<? extends ExtensionPointType> getExtensionPoints();`  
Your `ExtensionPointPage` implementation will rely on those implementations to drive itself. Your ExtensionPointPage itself should have a type parameter that maps to your ‘base’ record type - whatever common settings there are between your different item types - think things like name, description.  
See how it’s implemented on the AlarmJournalPage:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/7/d74b7007b18975f0145b9095633fc1deee0f1576.png)

Your base settings record should have (by convention) a StringField named Type:

```auto
    public static final StringField Type = new StringField(META, "Type", SFieldFlags.SMANDATORY,
        SFieldFlags.SDESCRIPTIVE
    );

```

Then, each ‘type’ of sub-configurable-thing you have needs to have its own `PersistentRecord` implementation, which will have a (by convention) Profile field referencing back to its parent, **and** a `BaseExtensionPoint` subclass, which will define a type ID (that ultimately ends up in the _base_ record’s `Type` field). This is what the `Profile` field should look like - only with the type parameters for your ‘base’ record class:

```auto
    public static final LongField ProfileId = new LongField(META, "ProfileId", SFieldFlags.SPRIMARY_KEY);
    public static final ReferenceField<AlarmJournalRecord> Profile = new ReferenceField<>(META,
        AlarmJournalRecord.META, "Profile", ProfileId
    );

```

It’s easiest to use the ‘conventional’ names for these things, because it makes everything else automatically work without having to override various other methods.

The ‘type’ that’s passed into `BaseExtensionPointType` as a constructor parameter is the same type that will be used to look up the extension point type on the `ExtensionPointManager` - this whole area ties together.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 24, 2020, 7:13pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/13 "2020-09-24T19:13:31Z")

</div>

> [@paul-griffith](#):
>
> public static final LongField ProfileId = new LongField(META, "ProfileId", SFieldFlags.SPRIMARY\_KEY); public static final ReferenceField Profile = new ReferenceField\<\>(META, AlarmJournalRecord.META, "Profile", ProfileId );

Thanks @paul-griffith. So do I have to make my own implementation of ExtensionPointManager if my Settings Panel will not be under opc devices, or alarming etc?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 24, 2020, 7:17pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/14 "2020-09-24T19:17:30Z")

</div>

Correct. It should probably be something you manage in your GatewayHook’s `setup`, `startup`, `shutdown` methods.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 24, 2020, 7:41pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/15 "2020-09-24T19:41:47Z")

</div>

> [@paul-griffith](#):
>
> Okay, so your ExtensionPointManager needs to be implemented. That should be the (effectively singleton) ‘manager’ that book-keeps all the individual instances you’re going to create.

I have created this.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/7/e7c8d9dc055e1c7095898fb4c2d07d12a8316020.png)

What is the method on setup/shutdown I call to add/remove this implementation to the gateway context? If such method exists..

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 24, 2020, 8:03pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/16 "2020-09-24T20:03:02Z")

</div>

The `ExtensionPointPage` needs to point back to the `ExtensionPointManager`. You don’t explicitly register the manager anywhere in the gateway hook - it’s just easiest to manage your module’s lifecycle using those methods. You _do_ have to register your ExtensionPointPage, via the config category/config panels on the `GatewayModuleHook`.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 24, 2020, 8:15pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/17 "2020-09-24T20:15:28Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/5/d577ffec2caecd516cb5eb8ce2889885e7bb4c00.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/c/bc0e3e70e60b9189b5628ef2ef61a144567a3a1c.png)  
@paul-griffith  
Do I need a field called “Profile” in my base records to complete this linkage? Module wont startup right now.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 24, 2020, 8:33pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/18 "2020-09-24T20:33:54Z")

</div>

Are you running `SchemaUpdater#updatePersistentRecords(com.inductiveautomation.ignition.gateway.localdb.persistence.RecordMeta<?>...)` in your module’s setup hook? You need to run that (every time!) to ensure all the fields your `PersistentRecord` defines are present in the IDB.

`SchemaUpdater` is accessible from `GatewayContext`.

---

<div class="post-metadata">

**Author:** ![cboin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@cboin](https://forum.inductiveautomation.com/u/cboin)\
**Post date:** [September 24, 2020, 8:37pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/19 "2020-09-24T20:37:24Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/6/e67e629f7ffaa6f250f8a8c08214ad9eeafd0a44.png)

I call this method on setup()

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/5/758de831648d6b3f804cdd32e6e5090907796932.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 24, 2020, 8:40pm UTC](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595/20 "2020-09-24T20:40:25Z")

</div>

Try clearing out your .idb and starting from scratch - it looks like you’ve got an already present record that’s breaking the contract you established on the `PersistentRecord`. If everything’s set up correctly with the extension point, then you shouldn’t be able to get a null profile.

[Next page](https://forum.inductiveautomation.com/t/ignition-settings-next-page/38595.md?page=2)
