# \[Feature-789\] Perspective component extensibility

**URL:** <https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459>\
**Category:** Ignition\
**Created:** [October 28, 2019, 7:14pm UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459 "2019-10-28T19:14:41Z")\
**Posts on this page:** 17\
**Page:** 2

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [May 11, 2023, 9:51am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/21 "2023-05-11T09:51:49Z")

</div>

I wasn't thinking about a js component, but something like a js script associated to views. Maybe a script on the root, like message handlers, or something like that.  
And js scripts in the library as well, that you could call from the special view js script...

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 11, 2023, 10:01am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/22 "2023-05-11T10:01:36Z")

</div>

that would make you think it is tied to only the view, but it wouldnt be.

a system.perspective.javescript("string") could be intersting though, if it sort of knows which compontnnet triggered it, would reduce the need of finding it in the document. but it would not work as easy as that

---

<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:** [May 11, 2023, 12:37pm UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/23 "2023-05-11T12:37:53Z")

</div>

> [@pascal.fragnoud](#):
>
> That there is no built-in way is not stopping anyone, it just makes it ugly.

Oh, but it greatly reduces IA's support surface. Probably a huge win for IA.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [May 11, 2023, 12:41pm UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/24 "2023-05-11T12:41:37Z")

</div>

yeah no need to pay javascripters, just tag me for free 😛

---

<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:** [May 11, 2023, 12:48pm UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/25 "2023-05-11T12:48:54Z")

</div>

@victordcq FWIW, I'm a huge fan of your work.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [August 22, 2023, 6:57am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/26 "2023-08-22T06:57:53Z")

</div>

Someone reminded me of this so i wipped something up  
[focusRow.zip](https://forum.inductiveautomation.com/uploads/short-url/as3VYUdazbWMcPq4lvM6SM4AfPq.zip) (37.1 KB)

had to use html parsing for " (&q uot;) because it was doig annyoing with the escaped characters xd (the disadvantage of parsing a string to js xd)

```auto
	
	code = """<img style='display:none' src='/favicon.ico' onload=\"	
		document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;]').scrollIntoView();	
		document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;] .content').click();				
	\"></img>""".replace("\n", "").replace("\t", "")
	return code
		

```

(vitualized must be off)

---

<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:** [August 22, 2023, 7:00am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/27 "2023-08-22T07:00:08Z")

</div>

Legend!

---

<div class="post-metadata">

**Author:** ![R\_S](https://avatars.discourse-cdn.com/v4/letter/r/a88e57/32.png) [@R\_S](https://forum.inductiveautomation.com/u/R_S)\
**Post date:** [August 24, 2023, 12:44am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/28 "2023-08-24T00:44:00Z")

</div>

Thanks for uploading that. I feel like I made every mistake along the way to getting this working but now know just enough to be dangerous now 😅

To clarify, this method requires that you make create a domId value in the table's meta properties which is then referenced in the markdown code along with the source of row selection (you also have to turn off the escapeHtml on the markdown component and also turn off virtualized in the table props). Am I missing anything?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [August 24, 2023, 6:17am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/29 "2023-08-24T06:17:46Z")

</div>

i think thats it yes, i had made a demo view.  
you probably want to make this conditional if nothing is selected

---

<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:** [September 30, 2023, 9:43pm UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/30 "2023-09-30T21:43:15Z")

</div>

Hooooow would you do this when virtualised is on? I have to have it on cause the table has so many rows it's super slow if it's off 😩

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [October 2, 2023, 7:27am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/31 "2023-10-02T07:27:37Z")

</div>

Alright alright, i'll use some mutation magic.  
Just be sure the row number exists else it will keep searching for it xd

Here you go 😉

(this code only works on virtualised grids)   
(nobody really cares if this is clean code or not so just puting in some empty try cacthes to keep it running xd)  
(it assumes all the rows have the same height)

```auto
code = """<img style='display:none' src='/favicon.ico' onload=\"	
		const heightRow = document.querySelector('#"""+value.id+""" .tr-group.ia_table __rowGroup.ia_table__ body__rowGroup').offsetHeight;
		const heightScroll = heightRow * """+value.number+""";
		const grid = document.querySelector('#"""+value.id+""" .ReactVirtualized__Grid');
		const callbackScrollOnce = (mutationList, observer) => {
				try{		
					document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;]').scrollIntoView();	
					document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;] .content').click();
					observer.disconnect();				
				} catch (error) {}
			};		
		const observerScroll = new MutationObserver(callbackScrollOnce);
		const scrollListener = document.querySelector('#"""+value.id+""" .ReactVirtualized __Grid__ innerScrollContainer');
		observerScroll.observe(scrollListener, { attributes: false, childList: true, subtree: true });
		grid.scrollTo(0,heightScroll);	
		try{		
			document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;]').scrollIntoView();	
			document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;] .content').click();
		} catch (error) {}	
	\"></img>""".replace("\n", "").replace("\t", "")
	return code

```

---

<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:** [October 2, 2023, 7:56am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/32 "2023-10-02T07:56:50Z")

</div>

😲  
Looking forward to trying this out next week when I'm back (or earlier more than likely if I'm honest.. haha)! Our client will be super happy to have this working!

Oops, forgot to say thanks!

---

<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:** [October 2, 2023, 11:27am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/33 "2023-10-02T11:27:57Z")

</div>

I just tested it, very nice!! One small thing is that it doesn't scroll to the right position if some of the rows aren't the default single-line height (e.g. their cell contents length has increased the height of the row).  
I try to avoid this anyway in this table though so shouldn't be an issue. Thanks again!

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [October 2, 2023, 11:31am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/34 "2023-10-02T11:31:02Z")

</div>

> [@nminchin](#):
>
> aren't the default single-line height

> [@victordcq](#):
>
> (it assumes all the rows have the same height)

Yes. Its not really possible to know how hieght every row since they havent been rendered yet, so the only way i see this possible is to just do this. Using the height of the first found rendered row.  
`const heightScroll = heightRow * """+value.number+""";`

i did put in an other scroll into view to try find it again if its close enough, but the virtualised table only renders a couple rows out of view, so this might not work with very varient rows.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [October 2, 2023, 11:36am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/35 "2023-10-02T11:36:24Z")

</div>

i guess it could be possible to make a smarter way to find it if it uses a couple of steps in between (ex after the first scroll to height, if it doesnt find the correct row number, check which rownumbers are in view and see how much you are short and adjust height to that...  
but that is a whole lot of work for somehting that wont be smoot and very confusing to watch the grid go up and down untill it finds the row xd

---

<div class="post-metadata">

**Author:** ![R\_S](https://avatars.discourse-cdn.com/v4/letter/r/a88e57/32.png) [@R\_S](https://forum.inductiveautomation.com/u/R_S)\
**Post date:** [March 13, 2024, 1:17am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/36 "2024-03-13T01:17:45Z")

</div>

Got a request for a slight modification @victordcq:

I have a table with subviews.  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/d/bd5aab394211363eba35437a186437c8279f66ac.png)

Using the below code in markdown still scrolls to the correct table row, however it no longer selects the row. Could you have a look? Also, bonus points if you can open the subview too?

```auto
code = """<img style='display:none' src='/favicon.ico' onload=\"	
		document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;]').scrollIntoView();	
		document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;] .content').click();				
	\"></img>""".replace("\n", "").replace("\t", "")
	return code

```

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [March 13, 2024, 7:56am UTC](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459/37 "2024-03-13T07:56:12Z")

</div>

with subviews you can use this, last line opens the subview;)

remember that for this version of the code, virtualized has to be off.  
i did post a version with mutation observers ifyou dont want to use virtualized

```auto
	code = """<img style='display:none' src='/favicon.ico' onload=\"			
			document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;]').scrollIntoView();			
			document.querySelectorAll('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;] .content')[1].click();	
			document.querySelector('#"""+value.id+""" [data-row-id=&quot;"""+str(value.number)+"""&quot;] .expand-subview').click();			
		\"></img>""".replace("\n", "").replace("\t", "")
	return code

```

[Previous page](https://forum.inductiveautomation.com/t/feature-789-perspective-component-extensibility/29459.md?page=1)
