# Musson Industrial's Embr-Periscope Module

**URL:** <https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047>\
**Category:** 3rd Party Modules\
**Tags:** perspective\
**Created:** [November 24, 2024, 10:26pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047 "2024-11-24T22:26:31Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [March 17, 2025, 12:47am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/22 "2025-03-17T00:47:21Z")

</div>

Sure:

**Use Case 1, Component Modification**

 ![java_KSPgT9298M](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/0/107386c34d1531a96b932ce35e73662330dd4bf1.png)

1. Adding extra buttons to the bottom of a tag browse tree.
2. Adding extra buttons to the header of an alarm table.
3. Assigning a `pattern` to an input text field (this example assigns a pattern that requires a PIN of exactly 4 numbers.

> **View JSON**
>
> ```python
> {
> "custom": {},
> "params": {},
> "props": {},
> "root": {
> "children": [
> {
> "meta": {
> "domId": "alarms",
> "name": "AlarmStatusTable"
> },
> "position": {
> "height": 280,
> "width": 613,
> "x": 5,
> "y": 422
> },
> "type": "ia.display.alarmstatustable"
> },
> {
> "children": [
> {
> "children": [
> {
> "meta": {
> "name": "Button"
> },
> "position": {
> "shrink": 0
> },
> "props": {
> "text": "Extra Action"
> },
> "type": "ia.input.button"
> }
> ],
> "meta": {
> "name": "FlexContainer"
> },
> "position": {
> "basis": "auto",
> "grow": 0,
> "shrink": 0
> },
> "props": {
> "style": {
> "margin": "0.5rem",
> "overflow": "visible"
> }
> },
> "type": "ia.container.flex"
> }
> ],
> "meta": {
> "name": "AlarmStatusTableExtras"
> },
> "position": {
> "height": 300,
> "width": 300,
> "x": 372,
> "y": 546
> },
> "props": {
> "element": "() \u003d\u003e document.getElementById(\u0027alarms\u0027).getElementsByClassName(\u0027toolbarTabContainer\u0027)[0]"
> },
> "type": "embr.periscope.embedding.portal"
> },
> {
> "meta": {
> "domId": "tagTree",
> "name": "TagBrowseTree"
> },
> "position": {
> "height": 387,
> "width": 257,
> "x": 16,
> "y": 21
> },
> "type": "ia.display.tag-browse-tree"
> },
> {
> "children": [
> {
> "children": [
> {
> "meta": {
> "name": "Button"
> },
> "position": {
> "grow": 1,
> "shrink": 0
> },
> "props": {
> "text": "Extra Action"
> },
> "type": "ia.input.button"
> },
> {
> "meta": {
> "name": "Button_0"
> },
> "position": {
> "grow": 1,
> "shrink": 0
> },
> "props": {
> "text": "Extra Action 2"
> },
> "type": "ia.input.button"
> }
> ],
> "meta": {
> "name": "FlexContainer"
> },
> "position": {
> "basis": "auto",
> "grow": 0,
> "shrink": 0
> },
> "props": {
> "alignContent": "center",
> "direction": "column",
> "style": {
> "gap": "0.5rem",
> "margin": "0.5rem",
> "overflow": "visible"
> }
> },
> "type": "ia.container.flex"
> }
> ],
> "meta": {
> "name": "TagBrowseTreeExtras"
> },
> "position": {
> "height": 300,
> "width": 300,
> "x": 372,
> "y": 546
> },
> "props": {
> "element": "() \u003d\u003e document.getElementById(\u0027tagTree\u0027)"
> },
> "type": "embr.periscope.embedding.portal"
> },
> {
> "meta": {
> "domId": "textField",
> "name": "TextField"
> },
> "position": {
> "height": 32,
> "width": 150,
> "x": 325,
> "y": 91
> },
> "props": {
> "text": "123"
> },
> "type": "ia.input.text-field"
> },
> {
> "meta": {
> "name": "TextFieldExtras"
> },
> "position": {
> "height": 300,
> "width": 300,
> "x": 372,
> "y": 546
> },
> "props": {
> "element": "() \u003d\u003e document.getElementById(\u0027textField\u0027)",
> "events": {
> "target": {
> "lifecycle": {
> "onMount": "(target) \u003d\u003e {\ntarget.pattern \u003d \u0027\\\\d{4,4}\u0027\n}"
> }
> }
> }
> },
> "type": "embr.periscope.embedding.portal"
> }
> ],
> "meta": {
> "name": "root"
> },
> "type": "ia.container.coord"
> }
> }
> 
> ```

**Use Case 2, Inverted Rendering**

This example uses a Portal to break out of the normal rendering structure in order to simplify view development. Here's the problem statement:

1. There is a main view, consisting of a header and a child view.
2. There are several different child views available for selection.
3. Depending on which child view is shown, different options need to be shown in the header.

In order to accomplish this without Portals, it is the responsibility of the main view to hide/show the different options (probably using some embedded views). 100% possible but kind of annoying to manage.

With Portals, each child view can directly add its options to the header. No conditional logic is needed on the main view, and no extra embedded views are needed for the option buttons. All of the configuration for the child view is contained inside the child view.

[periscope\_portal\_header\_example.zip](https://forum.inductiveautomation.com/uploads/short-url/gfPqRKAU6zI3NpwDW4gQWFclD7D.zip) (15.7 KB)

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [March 31, 2025, 11:06pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/23 "2025-03-31T23:06:00Z")

</div>

# The Toasts Update

[Periscope version 0.7.0](https://github.com/mussonindustrial/embr/releases/tag/%40embr-modules%2Fperiscope%400.7.0) includes toasts powered by [react-toastify](https://github.com/fkhadra/react-toastify).

> **[Release @embr-modules/periscope@0.7.0 · mussonindustrial/embr](https://github.com/mussonindustrial/embr/releases/tag/%40embr-modules%2Fperiscope%400.7.0)**
>
> Minor Changes
> 
> 
> b2f5657: Add Perspective client toast feature powered by https://github.com/fkhadra/react-toastify.
> This feature is accessed through the JavaScript scoped object periscope.toast usi...

The toasts also work in the designer 😉.

## Creating a Toast

These are client-side toasts, therefore all the interaction is done via [`system.perspective.runJavaScriptAsync`](https://docs.mussonindustrial.com/ignition/embr-periscope/scripting/perspective/system-perspective-runJavaScriptAsync).

`periscope.toast` is directly mapped to `react-toastify`'s `toast` object, all features are supported.

### Simplest Example

```python
system.perspective.runJavaScriptAsync('''() => {
	periscope.toast('Your first toast!')
}''')

```

## Embedded View Toast

This is somewhat advanced, but if you're reading this I trust you can figure it out.

A new helper function `perspective.createView` is available to remove the React/component store boilerplate; however, you still need to provide a unique and stable mount path. The easiest method for creating the mount path is by using the `toastId` available in the `toastProps` (basically just copy this example).

```python
system.perspective.runJavaScriptAsync('''() => {		
	periscope.toast(({ toastProps }) => {
		return perspective.createView({
			resourcePath: 'Path/To/Your/View',
			mountPath: `toast-${toastProps.toastId}`,
			params: {}
		})
	})
}''')

```

## More Information

For full details, check out the attached example views as well as the [react-toastify documentation](https://fkhadra.github.io/react-toastify).

## Example Views

[periscope\_toasts.zip](https://forum.inductiveautomation.com/uploads/short-url/7ZHpO2Bhkl0mS6vMqH9odrzoCM2.zip) (62.4 KB)

## Side Note

If you update to [Embr-Charts 2.2.4](https://github.com/mussonindustrial/embr/releases/tag/%40embr-modules%2Fcharts%402.2.4), you can also create toasts from within chart callbacks 😉 (the beginning of a shared JavaScript function registry system is in progress....)

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [April 1, 2025, 10:15am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/24 "2025-04-01T10:15:26Z")

</div>

> [@bmusson](#):
>
> ```python
> system.perspective.runJavaScriptAsync('''() => {		
> periscope.toast(({ toastProps }) => {
> return perspective.createView({
> resourcePath: 'Path/To/Your/View',
> mountPath: `toast-${toastProps.toastId}`,
> params: {}
> })
> })
> }''')
> 
> ```

Hey Ben, this looks sweet! Can you give us dummies over here (speaking only for myself of course) how you would structure the params dict? Is it literally just how you would normally in python?  
Can't wait to try these out on my current project 🙂

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 1, 2025, 3:27pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/25 "2025-04-01T15:27:53Z")

</div>

> [@nminchin](#):
>
> Is it literally just how you would normally in python?

Yup, that's exactly it. The keys of the params object are passed as the view's parameters.

As a refresher, you can pass arguments to `runJavaScriptAsync`; it takes a dictionary of arguments where the keys are mapped to the names of the arguments of the arrow function.

It's a mouthful, so here's an example:

```python
args = {
	'param': 'value1',
	'anotherParam': 'value2'
}

system.perspective.runJavaScriptAsync('''(param, anotherParam) => {
	console.log('param:', param)
	console.log('anotherParam:', anotherParam)
}''', args)

```

Using this you could build a reusable view-as-toast function by doing something like:

```python
# Definition
def showViewToast(viewPath, viewParams, toastOptions):
	
	args = {
		'viewPath': viewPath,
		'viewParams': viewParams,
		'toastOptions': toastOptions
	}
	
	system.perspective.runJavaScriptAsync('''(viewPath, viewParams, toastOptions) => {		
		periscope.toast(({ toastProps }) => {
			return perspective.createView({
				resourcePath: viewPath,
				mountPath: `toast-${toastProps.toastId}`,
				params: viewParams
			})
		}, toastOptions)
	}''', args)
	

# Usage
showViewToast(
	'Periscope/toasts/resources/EmbeddedView', 
	{ 'myParam': 'Text Value'}, 
	{ 'type': 'success', 'theme': 'colored' }
)

```

If you want access to toast-specific information you should pass those in as view params too. The example views show the `isPaused` status as well as the `toastId` (the `toastId` is used for interacting with the toast after it has been created, allowing you to close it, change its state/options, etc.).

Using the spread operator makes it pretty convenient:

```python
system.perspective.runJavaScriptAsync('''(viewPath, viewParams, toastOptions) => {		
	periscope.toast(({ toastProps }) => {
		return perspective.createView({
			resourcePath: viewPath,
			mountPath: `toast-${toastProps.toastId}`,
			params: {
				...viewParams, // Spread the viewParams object.
				toastId: toastProps.toastId // Also include the toastId.
			}
		})
	}, toastOptions)
}''', args)

```

---

<div class="post-metadata">

**Author:** ![calimero100582](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/calimero100582/32/18630_2.png) [@calimero100582](https://forum.inductiveautomation.com/u/calimero100582)\
**Post date:** [April 1, 2025, 3:51pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/26 "2025-04-01T15:51:21Z")

</div>

Tried it for the first time today. Looks really nice, but is there a reason for it to be so long to install/restart compared to other modules.

On the gateway, I go to Config -\> Modules, restart any module is almost instantaneous, but this one takes a long time, and when I get in the logs, I see that it triggered "Restarting gateway scripts..." on all our projects. Is there a way for me to prevent this?

---

<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:** [April 1, 2025, 3:57pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/27 "2025-04-01T15:57:40Z")

</div>

> [@calimero100582](#):
>
> I see that it triggered "Restarting gateway scripts..." on all our projects. Is there a way for me to prevent this?

Any module that supplies any jython extension function will trigger this, and it cannot be avoided.

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 1, 2025, 4:43pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/28 "2025-04-01T16:43:30Z")

</div>

What Phil said.

Also, in 8.3 hot loading of modules will be gone.

---

<div class="post-metadata">

**Author:** ![calimero100582](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/calimero100582/32/18630_2.png) [@calimero100582](https://forum.inductiveautomation.com/u/calimero100582)\
**Post date:** [April 1, 2025, 5:54pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/29 "2025-04-01T17:54:21Z")

</div>

Not planning on hot loading modules, our server started to use full CPU at the same moment I installed it, so, of course, it was a suspect to the performance issue, and the delay loading was bugging me. I am now sure this module was not the issue, but I needed to check

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [April 1, 2025, 8:22pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/30 "2025-04-01T20:22:03Z")

</div>

This is great, thanks for all the help, as always!  
I shouldn't (other priorities), but I'll most likely try this out today 😁

If there's ever another community service award at ICC like Phil received 2 years back, you'll be my first vote! 👍 @Carl.Gould

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [April 1, 2025, 11:04pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/31 "2025-04-01T23:04:21Z")

</div>

Slight issue, docks have a higher z-index than the toast does. Originally I didn't think the simple example was working, but it turned out it was showing underneath my side dock and navigation dock

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 2, 2025, 12:10am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/32 "2025-04-02T00:10:51Z")

</div>

Eek, a coworker just pointed this out too.

I think that the toasts should be contained within the center view and not overlap with the docks.  
Any objections?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [April 2, 2025, 1:21am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/33 "2025-04-02T01:21:07Z")

</div>

I think that'll work. I think most of the time I would be making it bottom-centred. It wooould be nice to have bottom right as well but over the top of docks, but if too hard then centre view is all good

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 2, 2025, 1:31am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/34 "2025-04-02T01:31:18Z")

</div>

I’d eventually like the top level `ToastContainer` to be configurable through session properties, however there’s no good mechanism at the moment for module authors to do that.

In the meantime I think having center-bound toasts is the safest option.

> **[Release @embr-modules/periscope@0.7.1 · mussonindustrial/embr](https://github.com/mussonindustrial/embr/releases/tag/%40embr-modules/periscope%400.7.1)**
>
> Patch Changes
> 
> 
> 7d41dd1: Perspective Toasts have been changed to respect mounted docked views.
> 
> Toasts are now contained within the center viewport.
> @embr-modules/periscope-web@0.7.1

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [April 2, 2025, 1:34am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/35 "2025-04-02T01:34:27Z")

</div>

Cheers!

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [April 2, 2025, 2:51am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/36 "2025-04-02T02:51:45Z")

</div>

With the the FlexRepeaterPlus, is there any way to get the row index automatically (without generating and pass in as a param)? I want to colour alternating rows differently, but not sure how. I can only see the `key` UUID

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 2, 2025, 3:10am UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/37 "2025-04-02T03:10:00Z")

</div>

> [@nminchin](#):
>
> row index automatically

It's an implicit parameter, it should be accessible by adding parameter named `index` in the child view.

I don't think it's documented anywhere...

Also a note about the UUID keys: there's nothing wrong with using the automatically generated UUIDs, but if you're generating the `instances` list from a binding/script you should be providing something more meaningful, like a database primary key or a unique ID.

As you add/remove/reorder the `instances` array, React uses the `key` property to track what changes are happening to each instance.

#### Example, deleting an instance:

```python
# Before
 index | key
---------------
   [0] | "key-0"
   [1] | "key-1"
   [2] | "key-2" <- To be deleted.
   [3] | "key-3"
   [4] | "key-4"

# After
 index | key
---------------
   [0] | "key-0"
   [1] | "key-1"
   [2] | "key-3"
   [3] | "key-4"

```

Order of operations:

1. You have 5 instances, each with unique keys.
2. You delete `instance[2]` from the list using the `popInstance()` method.
  - The `index` parameter for the instances is recalculated and updated on the gateway's model of the view.
  - This means bindings against the `index` will update immediately, even before the new `instances` list is ever rendered.

3. React sees the `instances` list has changed and re-renders.
  - It remembers that it had already rendered instances with keys `key-3` and `key-4` before, only now they are in different positions.
  - Nothing happens to instances `key-3` and `key-4`, except they have a new index.
  - This is the biggest difference between IA's version and the + version.

---

<div class="post-metadata">

**Author:** ![djs](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@djs](https://forum.inductiveautomation.com/u/djs)\
**Post date:** [April 2, 2025, 2:38pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/38 "2025-04-02T14:38:52Z")

</div>

Not sure about the FlexRepeaterPlus, but with the normal FlexRepeater, you can colour alternating rows using pure CSS. See this topic:

> [@Flex Repeater Alternating Row Colors using CSS](https://forum.inductiveautomation.com/t/flex-repeater-alternating-row-colors-using-css/99123):
>
> Didn't see a post about this yet, so I figured I'd share a simple example.This method uses pure CSS, so no need for script transforms. It does require the advanced stylesheet through. First, put this in your advanced stylesheet: .psc-flex-repeater-alt-rows:nth-child(odd) { background-color: lightblue; } .psc-flex-repeater-alt-rows:nth-child(even) { background-color: lightgreen; } (flex-repeater-alt-rows is the class name, while lightblue and lightgreen are the colors. These can be changed …

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 2, 2025, 3:45pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/39 "2025-04-02T15:45:36Z")

</div>

Yeah, you can totally do this with the Flex Repeater +. The DOM structure should be identical to the regular Flex Repeater.

---

<div class="post-metadata">

**Author:** ![hunterdg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/hunterdg/32/67774_2.png) [@hunterdg](https://forum.inductiveautomation.com/u/hunterdg)\
**Post date:** [April 7, 2025, 4:14pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/40 "2025-04-07T16:14:39Z")

</div>

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

FYI

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 7, 2025, 4:20pm UTC](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047/41 "2025-04-07T16:20:16Z")

</div>

> <https://github.com/mussonindustrial/embr/issues/265>
>
> When installing or starting the module, the following types of messages appear i…n the gateway's logs:
> 
> \`\`\`
> RefValidator 25Mar2025 10:29:33 Failed to resolve schema ref 'urn:ignition-schema:schemas/components/javascript-function.json', validation will not succeed!
> RefValidator 25Mar2025 10:29:33 Failed to resolve schema ref 'urn:ignition-schema:schemas/components/javascript-function.json', validation will not succeed!
> RefValidator 25Mar2025 10:29:33 Failed to resolve schema ref 'urn:ignition-schema:schemas/components/javascript-function.json', validation will not succeed!
> RefValidator 25Mar2025 10:29:33 Failed to resolve schema ref 'urn:ignition-schema:schemas/components/javascript-function.json', validation will not succeed!
> RefValidator 25Mar2025 10:29:33 Failed to resolve schema ref 'urn:ignition-schema:schemas/components/javascript-function.json', validation will not succeed!
> \`\`\`

Yeah it’s a thing 😟

@paul-griffith do you see anything wrong with this? It works in the designer, but complains in the gateway.

> <https://github.com/mussonindustrial/embr/blob/5b5066bf83858c968799f12808bdb2d0be5604bb/modules/periscope/common/src/main/resources/schemas/components/embr.periscope.embedding.view/props.json>

```python
…
        "style": {
            "$ref": "urn:ignition-schema:schemas/style-properties.schema.json",
            "default": {
                "classes": "",
                "overflow": "auto"
            }
        }
…

```

[Previous page](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047.md?page=1)

[Next page](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047.md?page=3)
