# Property Categories of AbstractVisionComponent Incorrect on Module Import

**URL:** <https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776>\
**Category:** 3rd Party Modules\
**Tags:** vision, ignition80\
**Created:** [October 25, 2024, 2:53pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776 "2024-10-25T14:53:59Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 25, 2024, 2:53pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/1 "2024-10-25T14:53:59Z")

</div>

Hi everyone,

I’m working on a custom Ignition Vision component that extends `AbstractVisionComponent` in Ignition 8.0.17, and I'm running into some issues with how properties are displayed in the Designer Property Editor. Specifically, all of my custom properties, as well as inherited ones from `AbstractVisionComponent` and `JComponent`, are being lumped into the `Misc` category, regardless of how I try to organize them in my `BeanInfo` class.

### Current Setup

Here’s an outline of my current setup:

- My component class, `ControlPanel`, extends `AbstractVisionComponent`.
- I’ve created a `BeanInfo` class (`ControlPanelBeanInfo`) to define the properties and their categories.
- I use `addProp()` in the `BeanInfo` class to define properties and specify their categories (e.g., "Data", "Appearance", etc.).

### The Problem

Even though I define categories for my properties in the `BeanInfo` class, when I drop the component onto a Vision window in the Ignition Designer, **all the properties show up under the `Misc` category** instead of being organized into the categories I specified (e.g., `Data`, `Appearance`, etc.).

Additionally, all the properties that `AbstractVisionComponent` inherits from `JComponent` are automatically included in the `Misc` category. This makes the property list cluttered and difficult to navigate.

### What I’ve Tried

1. **Categorizing Properties in `BeanInfo`:**  
I’ve used the `addProp()` method in my `BeanInfo` class to assign properties to categories like "Data" and "Appearance". Here’s an example of what my code looks like:

2. **Hiding Unwanted Inherited Properties:**  
I tried using `removeProp()` to hide some of the inherited properties that are cluttering the `Misc` category, but this didn't seem to have any effect either.

### Desired Outcome

What I would like to achieve is:

- Custom properties grouped under the appropriate categories (e.g., `Data`, `Appearance`, `Behavior`) as defined in the `BeanInfo` class.
- Reduce the number of inherited properties from `JComponent` that appear in the Property Editor, or at least hide the irrelevant ones.
- Ensure that properties added to the component are displayed in a clean, organized way in the Designer.

### Questions

1. **How can I ensure that properties show up in the correct categories in the Property Editor?**
2. **Is there a way to prevent inherited properties from `JComponent` from being automatically included under `Misc`?**
3. **Are there any alternative approaches or best practices for handling property organization in Ignition Vision components?**

Any help or suggestions would be greatly appreciated!

Thanks!

---

<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:** [October 25, 2024, 3:44pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/2 "2024-10-25T15:44:41Z")

</div>

Sounds like the designer is not even finding your BeanInfo class. Did you add your bean info package name to the search path (as shown in the Vision component example) ?

---

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 25, 2024, 3:45pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/3 "2024-10-25T15:45:46Z")

</div>

Literally just found that solution about 3 minutes ago. I have been fighting this for 2 days. Thank you for your prompt response.

---

<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:** [October 25, 2024, 4:41pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/4 "2024-10-25T16:41:46Z")

</div>

> [@Porter\_Ellis](#):
>
> Ignition 8.0.17

Side tangent, we're about to release 8.3; 8.1 has been out since November 2020. You should _really_ upgrade as soon as possible.

---

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 25, 2024, 4:46pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/5 "2024-10-25T16:46:59Z")

</div>

I am a system integrator working with some old Ignition projects. Customers don't always like to change things with a working system. I wholeheartedly agree that these projects should be upgraded to the most recent version, but the trick for me is convincing them to shell out the money/downtime for it.

---

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 25, 2024, 5:05pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/6 "2024-10-25T17:05:05Z")

</div>

As a side note, I am also trying to pre-bind a property to a tag in the module. Is there a simple way to do this, or is it pretty involved?

---

<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:** [October 25, 2024, 5:13pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/7 "2024-10-25T17:13:49Z")

</div>

> [@Porter\_Ellis](#):
>
> pre-bind a property to a tag in the module

It's involved, and a disaster for the poor soul who has to deal with this later. A 3rd party module should not be wiring up the data flow of a project. Just make the functionality **possible**.

---

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 25, 2024, 5:39pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/8 "2024-10-25T17:39:51Z")

</div>

Our goal is to provide control over a specific machine to the user, without letting the user mess with the functionality too much. Instead of directly creating the binding, could I create a tag change listener and populate the value of the property with the new value of the tag? If so, how would I do this? The examples are a little unclear about tag change listeners. This is the preliminary code I have:

```
private void bindTagToNumVal(String tagPath) throws IOException {
    // Parse the tag path correctly
    TagPath path = TagPathParser.parse(tagPath);

    // Create a listener for tag changes
    TagChangeListener listener = event -> {
        // When the tag value changes, handle the new value
        QualifiedValue newValue = event.getValue();
        handleTagChange(newValue); // Call the method to handle the new tag value
    };

    // Subscribe to tag changes using the tag path and listener
    tagManager.subscribeAsync(path, listener);
}

// Handle the tag change event
private void handleTagChange(QualifiedValue newValue) {
    if (newValue.getQuality().isGood()) {
        Double newTagValue = newValue.getValue() instanceof Double ? (Double) newValue.getValue() : 0.0;
        setNumVal(newTagValue); // Update NumVal property
    }
}

@Override
    protected void onStartup() {
        super.onStartup();
        try {
            bindTagToNumVal("[VTISControl]VTIS1/Phase Control/Phase1_Ster/Status/Phase Status");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

```

---

<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:** [October 26, 2024, 1:35pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/9 "2024-10-26T13:35:15Z")

</div>

Yes, a tag change listener is an option if the tag path is hard coded into your component (Ewww!). If not hard coded, just let the designer do it.

(Be sure that your listener delegates component property writes to the Event Dispatch Thread.)

---

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 28, 2024, 1:33pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/10 "2024-10-28T13:33:12Z")

</div>

The tag path will not be hardcoded, but couldn't I reasonably instantiate and remove listeners for that tag every time the tag path changes? If so, should I be doing this in the GatewayHook or on the component file itself? Or do I create the TagChangeListener class (found at [this forum post](https://forum.inductiveautomation.com/t/reading-tag-values-in-gateway-subscribing-to-tags/12232/2)) in the Common directory and use it where it is needed?

---

<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:** [October 28, 2024, 4:12pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/11 "2024-10-28T16:12:39Z")

</div>

You should do this in the component startup and shutdown events.

---

<div class="post-metadata">

**Author:** ![Porter\_Ellis](https://avatars.discourse-cdn.com/v4/letter/p/ed8c4c/32.png) [@Porter\_Ellis](https://forum.inductiveautomation.com/u/Porter_Ellis)\
**Post date:** [October 28, 2024, 6:14pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/12 "2024-10-28T18:14:01Z")

</div>

This is what I have:

```
    // Listener class to update numVal
private class TagValueChangeListener implements TagChangeListener {
    @Override
    public void tagChanged(TagChangeEvent event) {
        QualifiedValue qv = event.getValue();
        if (qv.getValue() instanceof Double) {
            setNumVal((Double) qv.getValue());
        }
    }
}

private void listen(String tagPath){
    listener = new TagValueChangeListener();
    try {
        context.getTagManager().subscribeAsync(TagPathParser.parse(tagPath), listener);
    } catch (IOException e) {
        logger.error(String.valueOf(e));
        throw new RuntimeException(e);
    }
}

@Override
protected void onStartup() {
    super.onStartup();
    listen(tagPath);
}

@Override
protected void onShutdown() {
    if (tagPath != null) {
        try {
            context.getTagManager().unsubscribeAsync(TagPathParser.parse(tagPath), listener);
        } catch (IOException e) {
            logger.error(String.valueOf(e));
            throw new RuntimeException(e);
        }
    }
    super.onShutdown();
}

public String getTagPath() {
    return tagPath;
}

public void setTagPath(String tagPath) throws IOException {
    this.tagPath = tagPath;
    listen(this.tagPath);
}

public Double getNumVal() {
    return numVal;
}

public void setNumVal(Double numVal) {
    Double old = this.numVal;
    this.numVal = numVal;
    firePropertyChange("numVal", old, numVal);
    if (numTest != null) {
        numTest.setValue(this.numVal);
    }
    repaint();
}

```

This does nothing in the Designer when changing the tagPath property. What am I missing?

---

<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:** [October 28, 2024, 6:26pm UTC](https://forum.inductiveautomation.com/t/property-categories-of-abstractvisioncomponent-incorrect-on-module-import/97776/13 "2024-10-28T18:26:10Z")

</div>

Not sure, but you are definitely leaking listeners when you change the tag path (you need to unsub the prior tagpath before subscribing the new). You are also assigning to a component property directly in your listener. Expect this to eventually crash your client and/or designer.

I think you are on your own. You are on a path that I disagree with, and I therefore have insufficient motivation to study your code.
