# 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:** 1\
**Showing post:** 22

<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)

---

_[View the full topic](https://forum.inductiveautomation.com/t/musson-industrials-embr-periscope-module/99047)._
