63
Views
3
Comments
Solved
[OutSystems UI] Tabs - How to unregister TabsRegisterCallback
outsystems-ui
Reactive icon
Forge asset by OutSystems
Application Type
Reactive

I am looking for a way to replace the internal Tabs.OnTabChangeHandler with a custom version via a simple wrapper component around the existing Tab component such that one can have the opportunity to prevent a tab from switching prior to it actually switching.

Looking into the code:

  • The Tabs.OnTabChangeHandler callback is registered to a customId that can be obtained via by calling TabsAPI.GetTabsById(WidgetId).
  • The internal TabsAPI.RegisterCallback is being called with the Tabs.OnTabChangeHandler action as the callback parameter.  The TabsAPI.RegisterCallback does not use the optional callback name parameter of the ICallback interface :(.
  • The actual Tabs.OnTabChangeHandler is the actor that triggers the tabs to change indexes; the Tabs.OnTabChangeHandler would be more accurately named as Tabs.OnBeforeTabChangeHander or TriggerOnTabChangeEvent.
  • The javascript object has a _platformEventTabsOnChange  object that does look like it should be changed directly.

The desired tab functionality can be obtained via deleting the one assignment in the Tabs.OnTabChangeHandler action, but I really do not want to clone the existing component and then be responsible handling merges on every OutSystemsUI version change.  Thus finding a mechanism to to replace the existing Tabs.OnTabChangeHandler is much more desirable.

2022-01-13 11-39-41
Bernardo Cardoso
Staff
Solution

Hi @erik berg,


About your use-case, before diving into more high-code solutions, did you try or does it help the following approaches:

  • Use both DisableTabItem and EnableTabItem Client Actions to prevent changing to a specific Tab Item, when needed?
  • Or with a CSS approach, have a utility-class with pointer-events: none, that is toggled on the ExtendedClass parameter of the TabsHeaderItem, when needed?


Regarding the JS approach:

  • Your name suggestion for the method makes sense yes. But, this is indeed the method that trigger the platform event, that's why the name. Maybe it would make sense, in some situations, to have a beforeEvent method also, and that's definitely something we might review in the future.
  • We are currently reviewing the way we might better enable high-code extensibility using our framework, also because of use-cases like yours. That being said, currently, overriding the _platformEventTabsOnChange is indeed the only way to do it, I believe. I attached an oml with a override working, that has the following code (not fully tested):


This is overriding the _platformEventTabsOnChange method, with a custom one, that first runs a beforeOnChange action, and then triggers the default OnTabsChange method (of course, you can change this to do other stuff).


There're other ways to do this, but it would require a lot more work, like doing a complete new Custom Tabs Class, that extends the OutSystems UI one: OSUIFramework.Patterns.Tabs.Tabs.


Note that you probably would want to map the placeholders and input parameters between the Tabs block and the Custom one, I just made the necessary changes to make it work with the override.


Let me know if it helped!


Best regards,

Bernardo Cardoso

 

TabsOnBeforeChange.oml
2022-11-12 11-28-30
Gonçalo Martins
Staff

Hi @erik berg 

First of all, thank you for bringing up this use case and is really nice to start seeing the community looking really seriously at the extensibility of our OS UI components.

In order to be able to explore a solution could you please explain the use case you want to achieve since I was not able to understand 100% the part when you mentioned: "an have the opportunity to prevent a tab from switching prior to it actually switching"?

Cheers,
GM

UserImage.jpg
erik berg

The current Tabs widget is geared for viewing read only or searchable content (this has been a common design oversight with the platform widgets for while in my opinion), where clicking on a new tab has little or no impact on current tab.

What if the Tabs widget was displaying form content?  Clicking on a new tab should have some mechanism that allows the current tab to cancel the tab switch from occurring.

Thus if current tab has form data and user clicks another tab, the desired functional is to.

 1.  Allow the current tab to see if the form data is dirty and calculate its validity.  If not dirty, perform the tab switch.

2.   Allow the current tab to indicate to the user that the form data is dirty with its validity and then ask the user how they wish to proceed (switch tab without save, switch tab with save (if valid), do not switch tabs).

3.  Switch tabs based on the user's decission.

Disabling other tabs prevents these tabs from being clicked; making the current selected tab act more like a modal dialog vs a tab.

The nice thing about OutSystems UI is that is limited to mostly to the same constraints the OutSystems developers have when creating there own web blocks.  The open source and ability to clone and look into the oml file to see how OutSystems does something is very useful.  The UI pieces of the OutSystem and the Web in general is complicated; the developer has access to multiple layers and they need to figure how to send and received messages between these layers. When developing in OutSystems, I think in regards to the following layers.

  • OutSystems Server side code
  • OutSystems Client side code
  • OutSystems Client side JavaScript Widget code
  • DOM JavaScript code
  • DOM HTML

Each layer has constraints on what it can and cannot pass to another layer.  The hard development work is finding ways around these constraints via code patterns.  Leveraging OutSystems UI code is an excellent resource.


  

2022-01-13 11-39-41
Bernardo Cardoso
Staff
Solution

Hi @erik berg,


About your use-case, before diving into more high-code solutions, did you try or does it help the following approaches:

  • Use both DisableTabItem and EnableTabItem Client Actions to prevent changing to a specific Tab Item, when needed?
  • Or with a CSS approach, have a utility-class with pointer-events: none, that is toggled on the ExtendedClass parameter of the TabsHeaderItem, when needed?


Regarding the JS approach:

  • Your name suggestion for the method makes sense yes. But, this is indeed the method that trigger the platform event, that's why the name. Maybe it would make sense, in some situations, to have a beforeEvent method also, and that's definitely something we might review in the future.
  • We are currently reviewing the way we might better enable high-code extensibility using our framework, also because of use-cases like yours. That being said, currently, overriding the _platformEventTabsOnChange is indeed the only way to do it, I believe. I attached an oml with a override working, that has the following code (not fully tested):


This is overriding the _platformEventTabsOnChange method, with a custom one, that first runs a beforeOnChange action, and then triggers the default OnTabsChange method (of course, you can change this to do other stuff).


There're other ways to do this, but it would require a lot more work, like doing a complete new Custom Tabs Class, that extends the OutSystems UI one: OSUIFramework.Patterns.Tabs.Tabs.


Note that you probably would want to map the placeholders and input parameters between the Tabs block and the Custom one, I just made the necessary changes to make it work with the override.


Let me know if it helped!


Best regards,

Bernardo Cardoso

 

TabsOnBeforeChange.oml
Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.