# Iterate Through Components In Container (Vision)

**URL:** <https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512>\
**Category:** Ignition\
**Tags:** ignition81, scripting, vision\
**Created:** [January 19, 2024, 5:17pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512 "2024-01-19T17:17:38Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [January 19, 2024, 5:17pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/1 "2024-01-19T17:17:38Z")

</div>

(v8.1.35)

I have a need to iterate through multiple components within a container.

Each component is an easychart and I want to be able to go through each one and perform the same script. Rather than manually call the script for each chart and having to manually add/remove calls as charts are added/removed I would like to just loop through all of the components in the container.

Based on [this](https://forum.inductiveautomation.com/t/iterating-through-components-on-a-screen-through-scripting/16335) post I thought I would be able to use the `.component` object to iterate through the component list.

```auto
#get the container that holds all of the charts
chartsContainer = system.gui.getParentWindow(event).getComponentForPath('Root Container.Charts')

#for each chart in the container, update the path to the tagPen as needed
for easyChart in chartsContainer.component:
	Trending.historyPathConvert_MasterToEdge(easyChart)

```

I get the following error.

```auto
Traceback (most recent call last):
  File "<event:visionWindowOpened>", line 5, in <module>
AttributeError: 'com.inductiveautomation.factorypmi.application.com' object has no attribute 'component'

	at org.python.core.Py.AttributeError(Py.java:176)
	at org.python.core.PyObject.noAttributeError(PyObject.java:965)
	at com.inductiveautomation.factorypmi.application.script.PyComponentWrapper.noAttributeError(PyComponentWrapper.java:563)
	at org.python.core.PyObject. __getattr__ (PyObject.java:959)
	at org.python.pycode._pyx31.f$0(<event:visionWindowOpened>:5)
	at org.python.pycode._pyx31.call_function(<event:visionWindowOpened>)
	at org.python.core.PyTableCode.call(PyTableCode.java:173)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1703)
	at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:804)
	at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:207)
	at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:300)
	at com.inductiveautomation.factorypmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:57)
	at jdk.proxy2/jdk.proxy2.$Proxy46.visionWindowOpened(Unknown Source)
	at com.inductiveautomation.factorypmi.application.FPMIWindow.fireVisionWindowOpened(FPMIWindow.java:719)
	at com.inductiveautomation.factorypmi.application.VisionDesktop$RuntimeWindowOpener.openWindow(VisionDesktop.java:549)
	at com.inductiveautomation.factorypmi.application.VisionDesktop.openWindow(VisionDesktop.java:192)
	at com.inductiveautomation.factorypmi.application.VisionDesktop.openWindow(VisionDesktop.java:184)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.lambda$swapWindow$0(NavUtilities.java:197)
	at com.inductiveautomation.factorypmi.application.script.builtin.WindowUtilities.doGUIAction(WindowUtilities.java:853)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.swapWindow(NavUtilities.java:196)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.swapTo(NavUtilities.java:105)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.swapTo(NavUtilities.java:92)
	at com.inductiveautomation.factorypmi.application.components.tabstrip.PMITabStrip.setSelectedTab(PMITabStrip.java:482)
	at com.inductiveautomation.factorypmi.application.components.tabstrip.TabHolderPanel.mousePressed(TabHolderPanel.java:243)
	at java.desktop/java.awt.AWTEventMulticaster.mousePressed(Unknown Source)
	at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
	at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.Component.processEvent(Unknown Source)
	at java.desktop/java.awt.Container.processEvent(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

Ignition v8.1.35 (b2023120517)
Java: Azul Systems, Inc. 17.0.8

```

I used the property browser to make sure I got the correct path to the Charts container, and I also confirmed that it is a container and not a group.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [January 19, 2024, 5:25pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/2 "2024-01-19T17:25:05Z")

</div>

> [@amarks](#):
>
> `chartsContainer.component`

It should be:

```auto
chartsContainer.components

```

or this will also work:

```auto
chartsContainer.getComponents()

```

**Edit:** added bean property option per the feedback below

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 19, 2024, 6:05pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/3 "2024-01-19T18:05:51Z")

</div>

> [@justinedwards.jle](#):
>
> `chartsContainer.getComponents()`

better would be:

```auto
chartsContainer.components

```

---

<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:** [January 19, 2024, 6:35pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/4 "2024-01-19T18:35:36Z")

</div>

Important caveats to note:  
Your current approach doesn't check if the component is actually a chart, and your current approach doesn't do a "deep" walk, in case there's any nested container that itself contains a chart.

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [January 19, 2024, 6:43pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/5 "2024-01-19T18:43:27Z")

</div>

You can modify this function to make it work for you - [Fetching a component's data from window and transfer that value to Translation Manager - #2 by bkarabinchak.psi](https://forum.inductiveautomation.com/t/fetching-a-components-data-from-window-and-transfer-that-value-to-translation-manager/75007/2)

This does a recursive call for inner containers.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [January 19, 2024, 7:19pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/6 "2024-01-19T19:19:07Z")

</div>

That's what I had that caused the error

\*edit: I see I was missing the "s". Should be component **s** not `component`

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [January 19, 2024, 7:20pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/7 "2024-01-19T19:20:03Z")

</div>

I don't have a need for that here, but good to know.

Thanks

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 19, 2024, 7:21pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/8 "2024-01-19T19:21:58Z")

</div>

No you had `chartsContainer.component`, not `chartsContainer.components` notice the **s**

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [January 19, 2024, 7:27pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/9 "2024-01-19T19:27:29Z")

</div>

Why is it better?

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [January 19, 2024, 8:07pm UTC](https://forum.inductiveautomation.com/t/iterate-through-components-in-container-vision/84512/10 "2024-01-19T20:07:45Z")

</div>

I'll let @pturmel tell you. 😉

> [@"java import" in script](https://forum.inductiveautomation.com/t/java-import-in-script/68953/2):
>
> java's `getXyz()` and `setXyz(val)` are automatically mapped to jython property `xyz` via jython's internal java machinery that implements `@property`. So both the original java methods and a python-style property become available on such "NetBeans" objects. Using the property is fewer opcodes for the jython interpreter, so should be used wherever applicable.

Basically, anytime in ignition you see a method with signatures `get*(), set*(), and is*()` you should prefer to use the jython property instead. So `.getComponents()` becomes `.components`.

I don't believe that this happens for anything other than default getters and setters, and the standard boolean gettter `.isXyz()`
