# When to refresh the binding on a table edited by multiple-clients?

**URL:** <https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652>\
**Category:** Ignition\
**Created:** [February 20, 2021, 4:28pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652 "2021-02-20T16:28:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 20, 2021, 4:28pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/1 "2021-02-20T16:28:26Z")

</div>

I’ve got a simple configurations table in my _Perspective_ application. It’s used to populate various dropdowns in other views. Multiple users can edit the table. It seems to me …

1. I don’t want a polling binding to the database as it’s wasteful.
2. I want to keep the user in the same pager page and on the same selected row. The binding refresh would have to respect that.
3. I should indicate to the user that the data has been changed and, perhaps, give the opportunity to refresh by button.

How do others manage this? Do I create a memory tag to log the last update time and bind the refresh button’s visibility to that?

Any ideas?

---

<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:** [February 20, 2021, 4:55pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/2 "2021-02-20T16:55:41Z")

</div>

Sounds like a job for message handlers.  
When a client saves changes, a message is sent to all other clients informing them a change has taken place. Then you can either refresh the table automatically or prompt the user to manually refresh.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 20, 2021, 6:29pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/3 "2021-02-20T18:29:06Z")

</div>

OK. I’ll read up on those. I’ve watched the video so I should be able to figure it out.

Thanks.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 12:27pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/4 "2021-02-21T12:27:03Z")

</div>

I can't get this to work reliably. (I thought I saw it work once between a Chrome and Edge browser on the one PC.)

Here's the **sendMessage** in my table's _onEditCellCommit_ script:

```auto
			msg = system.util.sendMessage(
				project = system.project.getProjectName(),
				messageHandler = 'configUpdate', 
				payload = {'table': 'config'}, 
				scope = "C"
			)

```

Here's the _Edit Message Handler_ to set my table refresh button's visibility. It's on the button's Message Handlers _configUpdate_ script.

```auto
def onMessageReceived(self, payload):
	system.perspective.print('configUpdate message received')
	if payload.has_key('table'):
		if payload['table'] == 'config': # Corrected after code_skin's comment.
			self.meta.visible = True
			system.perspective.print('Refresh visible')
			

```

I have the Listen Scopes set to Session + Page + View in an attempt to get it to work. The message handler is not firing on update of the table cell.

Can anyone clarify what settings I require to sendMessage all active clients that the table has been update?

1. What scope should be specified in the sendMessage?
2. What scope should be specified in the message handler?

Update: When I print the _msg_ variable I get the following which I suspect is one of our guys using the _Vision_ client version of the application. I don't see any sign of me using the _Perspective_ version.

> [type=Client,sessionId=D292FDD2,clientAddress=10.X.X.X,clientHostName=UsersHostname, project=MyProject,messageHandler=configUpdate,filterParams={userRoles=, scope=C, userZones=},sendStatus=SENT]

Many thanks.

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [February 21, 2021, 12:36pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/5 "2021-02-21T12:36:23Z")

</div>

> [@Transistor](#):
>
> if payload.['table'] = 'config':

This might be an issue.

Try:  
`if payload['table'] == 'config':`

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 12:48pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/6 "2021-02-21T12:48:02Z")

</div>

Oops! Thanks. I’ve fixed that but the event isn’t being called. I have _system.perspective.print_ statements before that and they don’t execute.

Can you spot anything with my scoping?

Thanks!

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [February 21, 2021, 12:53pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/7 "2021-02-21T12:53:08Z")

</div>

> [@Transistor](#):
>
> project = system.project.getProjectName(),

~~This looks wrong too. try changing this to `system.util.getProjectName()`~~  
nvm.

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [February 21, 2021, 12:56pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/8 "2021-02-21T12:56:54Z")

</div>

Yes, what is scope='C' ?

You need to specify perspective scopes here; session, page, or view

> String scope - The scope that the message should be delivered to. Valid values are "session", "page", or "view". If omitted, "page" will be used. [optional]

[https://docs.inductiveautomation.com/display/DOC81/system.perspective.sendMessage](https://docs.inductiveautomation.com/display/DOC81/system.perspective.sendMessage)

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 1:04pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/9 "2021-02-21T13:04:06Z")

</div>

They seemed to use shorthand 'S', 'C' or 'G' (gateway) somewhere in the documentation. I've changed to 'session' and the returned value from _sendMessage_ is

> [type=Session,sessionId=5a8074b9-acde-4b50-b52f-c17380322f84,  
> project=MyProject,  
> messageHandler=configUpdate,  
> filterParams={userRoles=, scope=session, userZones=},  
> isRequest=no,  
> sendStatus=SENT,  
> type=Session,  
> sessionId=dbf2304c-01bf-4ffa-b3fd-5aba862d7341,  
> project=MyProject,  
> messageHandler=configUpdate,  
> filterParams={userRoles=, scope=session, userZones=},  
> isRequest=no,  
> sendStatus=SENT]

Am I right in thinking that I can send directly from one client to all the others? I don't need to send it to the gateway and have it broadcast it, do I?

---

<div class="post-metadata">

**Author:** ![code\_skin](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@code\_skin](https://forum.inductiveautomation.com/u/code_skin)\
**Post date:** [February 21, 2021, 1:17pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/10 "2021-02-21T13:17:58Z")

</div>

> [@Transistor](#):
>
> system.util.sendMessage

Oh. I think you want to use system.perspective.sendMessage and not util.sendMessage. they are different.

---

<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:** [February 21, 2021, 1:19pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/11 "2021-02-21T13:19:05Z")

</div>

You are confusing system.util.sendMessage with system.perspective.sendMessage. In this case, if all editing is done in Perspective, sending to Perspective’s session scope should be the right answer.

---

<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:** [February 21, 2021, 1:21pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/12 "2021-02-21T13:21:39Z")

</div>

> [@Transistor](#):
>
> I don’t need to send it to the gateway and have it broadcast it, do I?

Perspective scripts are already running in the gateway.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 1:23pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/13 "2021-02-21T13:23:09Z")

</div>

Doesn't _system.perspective.sendMessage_ only send the the client the code is triggered from.

> Send a message to a message handler within the same session. [system.perspective.sendMessage](https://docs.inductiveautomation.com/display/DOC81/system.perspective.sendMessage).

I want to notify all clients that the table has been updated.

---

<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:** [February 21, 2021, 1:25pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/14 "2021-02-21T13:25:45Z")

</div>

Ah, yes, you **do** need system. **util**.sendMessage, but with scope=‘S’. Scope ‘C’ broadcasts to _Vision_ clients.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 1:32pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/15 "2021-02-21T13:32:50Z")

</div>

Thanks, guys. No success yet. When I run the following code the first two messages return the expected values but _msg_ is empty.

```auto
	msg = system.perspective.sendMessage(
		project = system.project.getProjectName(),
		messageHandler = 'configUpdate', 
		payload = {'table': 'config'}, 
		scope = "S"
	)
	system.perspective.print(system.project.getProjectName())
	system.perspective.print('sendMessage configUpdate')
	system.perspective.print(msg)

```

---

<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:** [February 21, 2021, 1:34pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/16 "2021-02-21T13:34:50Z")

</div>

See edited emphasis above.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 1:47pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/17 "2021-02-21T13:47:42Z")

</div>

Thanks, Phil. (I'm blaming you for that one from earlier. 😉)

Now I'm getting a response to my _sendMessage_:

> [type=Session,sessionId=5a8074b9-acde-4b50-b52f-c17380322f84,  
> project=MyProject,  
> messageHandler=configUpdate,  
> filterParams={userRoles=, scope=S, userZones=},  
> isRequest=no,  
> sendStatus=SENT,  
> type=Session,  
> sessionId=dbf2304c-01bf-4ffa-b3fd-5aba862d7341,  
> project=MyProject,  
> messageHandler=configUpdate,  
> filterParams={userRoles=, scope=S, userZones=},  
> isRequest=no,  
> sendStatus=SENT]

so it looks like it's seeing another client. The clients still aren't triggering. (I just have a _system.perspective.print_ in the _onMessageReceived_ for now. Listen Scopes is set to _Session_.)

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 2:53pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/18 "2021-02-21T14:53:44Z")

</div>

Reading through the documentation again, I'm beginning to think that component message handlers can't see _system.util.sendMessage_ messages but only _system.perspective.sendMessage_ messages. [Component message handlers](https://docs.inductiveautomation.com/display/DOC81/Component+Message+Handlers) says:

> The idea being that some other component will broadcast a message, and if the type of the message matches what the Message Handler is listening for, the Message Handler will execute a script.

That means I am going about this the wrong way and that I need to:

1. Create a _Project Browser | Session Events | Message | configUpdate_ session message handler to receive a broadcast message.
2. Have that create a _system.perspective.sendMessage_ and pass the payload to the components in the session.

I can't get the session message handler to detect the incoming message though.

Am I on the right track?

---

<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:** [February 21, 2021, 8:07pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/19 "2021-02-21T20:07:03Z")

</div>

> [@Transistor](#):
>
> That means I am going about this the wrong way and that I need to:  
> ...

It's a little bit simpler than that.  
system.perspective.sendMessage() takes a _sessionID_ parameter that you can use to directly send messages to other sessions.

Try something like this:

```auto
def broadcastPerspectiveMessage(messageType, payload):
	"""Broadcast a Perspective message to all sessions in the current project."""
	project = system.util.getProjectName()
	sessions = system.perspective.getSessionInfo(projectFilter=project)	
	scope = 'session'
	for session in sessions:
		try:
			system.perspective.sendMessage(messageType, payload, scope=scope, sessionID=session['id'])
		except:
			# Try/except to avoid 'Unvalid UUID String' errors from open designer sessions.
			pass

```

Then on your save button:

```auto
payload = {
	'sessionID': self.session.props.id
}
shared.util.broadcastPerspectiveMessage("ConfigTableSaved", payload)

```

And on a message handler on your table (with message type of _ConfigTableSaved_ listening to _Session_ messages):

```auto
if payload['sessionID'] == self.session.props.id:
	# Do something on the session that initiated the save.
	pass
else:
	# Do something on all other listening sessions.
	pass
		
# Do something for all sessions.
pass

```

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [February 21, 2021, 8:59pm UTC](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652/20 "2021-02-21T20:59:18Z")

</div>

Thanks for this information. I haven’t found anything like this. All the documentation and examples suggest that I can just send a broadcast using _system.util.sendMessage_ and the others will pick it up. Your approach seems to target them all individually.

Q1. Where does the _broadcastPerspectiveMessage_ code go? Scriptiong | Project Library or on the gateway?  
Q2. You seem to be bypassing the Session Event message handler and going directly to the component message handler. Can you do that?

[Next page](https://forum.inductiveautomation.com/t/when-to-refresh-the-binding-on-a-table-edited-by-multiple-clients/43652.md?page=2)
