Adding a Web Block to a page dynamically

Adding a Web Block to a page dynamically

  
I am currently working on a project to allow a user to add a web block to their page from a list of available web blocks.  Is there any functionality in outsystems to pull a list of web blocks from the existing application in order to display it in a combo box or something like that?
Hi Jason,
 
I don't know if there exist some application in forge that does that kind of thing, but a easy solution is put the web blocks availables inside a container, one web block inside one container and for each container set, on the display setting, an expression that validate if the container with the web block will be showed or not.  Then you create a combo box where you show the options you want and then when the user choose one of them an variable will hold one value, and this is value that you will use to validate the expression on the containers, If the expression is True, the container will be showed, if it's the expression it's False, then the container will not be showed. I don't know if it's a solution for your problem or if is the best way to do it, try to see if make sense for you.
 
Regards,
Gonçalo Azambujo
Hi Jason,

Just a teaser but I think you are better of teaching OutSystems Platfrom to that user and have him build his pages :)

EDIT: You can use IFs and a user configuration on a database table that you'll have to program to indicate what web block to show on that page. Can you drill down a bit on what you want to build, why is this need to have the user select which web blocks are shown on the page? Thanks!
Just as mentioned, it's not too hard to do.. one solution is to add all web blocks to given page. Setup a configuration variable along with if widgets to turn on and off specific web block. (this solution is ok when you don't have many web blocks)
Thanks Gonçalo and Robert.  Unfortunatly, the application that we are trying to build will potentially have hundreds of available "widgets" to add to a users page, so we cannot load them all (even hidden) when the user requests the page.  

André, the goal for us is to create a single web page that is able to be personalized and saved, sort of like the old "iGoogle" concept where people might choose an "rss Feed" widget and a "weather" widget etc... and add it to their personal page, which would be persisted.
Jason -

We did something very similar to this a few years ago. We made a "library" of dashboard widgets and let people add them to a screen, rearrange them, etc. So I can tell you that it is well within the technical abilities of the platform (and no, you do NOT need to resort to using backdoor, unsupported methods to make this work).

Here's what we learned:

PROS

* Looks good in a sales demo.

* Provides powerful functionality to those that use it.

* Looks great in a sales demo.

* Checks the "dashboard" box when we compare to competitors.

* Looks AMAZING in a sales demo.

CONS

* Can be very slow & resource intensive. If each widget takes... say... up to a second or two to run (reasonable in our case, they are pulling real-time reporting numbers)... and someone loads the screen up with widgets... it makes the screen slow. Guess who gets held accountable? US! So the end user has constructed a disaster of a UI for themselves, then blames us for it being slow... and it kills our servers in the process.

* No one uses it... I pulled numbers a few weeks ago, we have 7,000+ users with access to the dashboard, in one week we saw 500 total hits to it, half were the same user.

* No one...I mean NO ONE... knows that you can do the customization. Again, 7,000+ users in the system have access to these dashboards, and there are a very small number of custom layouts, and each one is a slow performer because so many widgets are on them.

* The widgets look gorgeous (have I mentioned that our sales team loves demo'ing them? ;) ), but the information on them is poor. We have a bunch of items in the "library" but none of them really say "this is the state of your business". Instead, users have to look at a bunch of them on the screen and combine things like "revenue per month" and "customers lost/gained per month" etc. in their head to say, "is my business improving or declining?"

* It took nearly a month to put together. A lot of that was self-inflicted, we insisted on doing drag/drop and at the time the Forge's drag/drop stuff did not work well for us (we wanted multi-column drag/drop). That's changed... we put our drag/drop component in the Forge and I know there's another one out there too that looks good.

* Drag/drop is not a common paradigm on the Web. People don't realize they can use it. Even the couple of folks who customize don't know they can drag/drop. Drag/drop was not an effective use of our time.

* Even without drag/drop it is a lot of time/effort to create, test, and maintain each of those widgets.

BOTTOM LINE

* If you are really set on doing this, I'd be glad to detail for you what we did. There's nothing technical stopping you from doing this.

* If I went back in time, I'd take the numbers from the system today, go to the project planning meeting and argue for a static dashboard page that shows a pre-determined list of widgets. Let us tune it for performance, give them the best possible experience based on what we've learned, and make sure that the 4 - 8 widgets give them actionable information instead of throwing a bunch of "data" at them to try to figure out what the actionable information is.

* This was an expensive project in terms of man hours and continues to be a drag in terms of headaches and maintenance.

* The big benefits we got were "checking the box" on feature set and looking good in sales demos.

Again... I'd be happy to share with you the "under the hood" of what we did... but our experience with a very similar project was not positive, and not for technical reasons.

J.Ja
Thanks Justin,

I am very familiar with difficulties surrounding user acceptance of new technologies, so I see your frustration and have experienced it first hand in other projects as well.  I am still curious about the technical aspect of how you were able to manipulate outsystems to perform this functionality without simply embedding custom js to do it.
Jason -

Gotcha.

Here's what we did:

* Made a Static Entity representing the list of Widgets. It's not automatic to pull them, but it's a small item to maintain.

* Made a block for "Widget". In the block is a bucnh of If's based on that WidgetId to display the correct Web Block. Nothing fancy/automated here, but again, it's a few moments of work and not a big deal.

* Made a "Dashboard" entity that defined a Dashboard name, who owned it, etc.

* Made a "DashboardWidget" entity to tie Widgets to Dashboards, and added in an X and Y value representing which column and distance from the top it was.

* We limited the dashboard to 3 columns because of the width of our widgets.

* On the Dashboard screen, we had 3 Containers (one for each column) and in each one was a RecordList Widget with a Container, and inside the container we had our Widget Web Block and passed it the ID of the Widget to load.

* We made a Dashboard editor that allowed Drag/Drop and had an "Add" system to take Widgets from the "library", add them to the screen and move them around.

All easy stuff, except the drag/drop which was a hassle. Sure, it isn't going to be quite as automated as pulling a list of Web Block from a DB somewhere, but given the effort to make any given Widget in the first place, we felt that the work to add a Static Entity Record to enable it just wasn't a big deal.

Hope this helps!

J.Ja
Hi Justin,
Very cool stuff! Thanks for sharing pros, cons and your overall experience. Kudos to you!

Cheers
Thanks Justin, that helps alot with the construct of dynamically displaying blocks.  I'm still trying to determine if it is possible to get a list of public web blocks from all apps in outsystems and display them in a combo box or list somehow.  Sounds like you did that part manually.
Jason -

Yes, did it manually, but it takes but a few seconds to add it in, while the Widgets were hours or days each to write... really not a big deal.

You aren't likely going to find an enumerated list of Web Blocks anywhere... I've never seen such a thing. :(

J.Ja

Justin James wrote:

Jason -

Gotcha.

Here's what we did:

* Made a Static Entity representing the list of Widgets. It's not automatic to pull them, but it's a small item to maintain.

* Made a block for "Widget". In the block is a bucnh of If's based on that WidgetId to display the correct Web Block. Nothing fancy/automated here, but again, it's a few moments of work and not a big deal.

* Made a "Dashboard" entity that defined a Dashboard name, who owned it, etc.

* Made a "DashboardWidget" entity to tie Widgets to Dashboards, and added in an X and Y value representing which column and distance from the top it was.

* We limited the dashboard to 3 columns because of the width of our widgets.

* On the Dashboard screen, we had 3 Containers (one for each column) and in each one was a RecordList Widget with a Container, and inside the container we had our Widget Web Block and passed it the ID of the Widget to load.

* We made a Dashboard editor that allowed Drag/Drop and had an "Add" system to take Widgets from the "library", add them to the screen and move them around.

All easy stuff, except the drag/drop which was a hassle. Sure, it isn't going to be quite as automated as pulling a list of Web Block from a DB somewhere, but given the effort to make any given Widget in the first place, we felt that the work to add a Static Entity Record to enable it just wasn't a big deal.

Hope this helps!

J.Ja

Justin,

The only part I'm not getting is the "Widget Block". I don't see how to dynamically say "load this web block".  Or did you load a web block up with all of the widgets and then just hide all of the ones not current?


Kevin Swanson wrote:

Justin James wrote:

Jason -

Gotcha.

Here's what we did:

* Made a Static Entity representing the list of Widgets. It's not automatic to pull them, but it's a small item to maintain.

* Made a block for "Widget". In the block is a bucnh of If's based on that WidgetId to display the correct Web Block. Nothing fancy/automated here, but again, it's a few moments of work and not a big deal.

* Made a "Dashboard" entity that defined a Dashboard name, who owned it, etc.

* Made a "DashboardWidget" entity to tie Widgets to Dashboards, and added in an X and Y value representing which column and distance from the top it was.

* We limited the dashboard to 3 columns because of the width of our widgets.

* On the Dashboard screen, we had 3 Containers (one for each column) and in each one was a RecordList Widget with a Container, and inside the container we had our Widget Web Block and passed it the ID of the Widget to load.

* We made a Dashboard editor that allowed Drag/Drop and had an "Add" system to take Widgets from the "library", add them to the screen and move them around.

All easy stuff, except the drag/drop which was a hassle. Sure, it isn't going to be quite as automated as pulling a list of Web Block from a DB somewhere, but given the effort to make any given Widget in the first place, we felt that the work to add a Static Entity Record to enable it just wasn't a big deal.

Hope this helps!

J.Ja

Justin,

The only part I'm not getting is the "Widget Block". I don't see how to dynamically say "load this web block".  Or did you load a web block up with all of the widgets and then just hide all of the ones not current?


For each WebBlock in the Static Entity that enumerates the blocks, put an If widget. In the condition say WebBlockId (or whatever you pass in to Widget Block to tell it which block to display) = WebBlock.XYZ... and in the "True" part of the If, put Web Block XYX.

So you end up with a single WebBlock that you can call, passing a WebBlockId, and have it show the correct WebBlock.

Do NOT use a "hide" via CSS. Use an If widget. Otherwise it will run the preparation for all of the hidden Web Blocks.

J.Ja


A side from the technical background and the truly entertaining multiple references to "Looks Great in Sales Demo". I would suggest approaching the project in phases. You may pitch the idea of instead of hundreds of widgets that they prioritize a short list (5 - 10) that would be built in the initial roll out. After production roll out let some time pass and then see if they really need more widgets. As you all seem aware, asking for the blue sky is most detrimental to the success of a project.  

Dredging up an old thread but there is a very easy way to achieve this. Rather than creating the components as web blocks do them as a full standalone pages. Then use a database table and expression to create iframes which embed the pages onto your screen. You can even add drag and drop to move the iframes around the page and save the positions. 

This way each page is completely independent and you can even set individual pages to autorefresh.



John -

What's the advantage compared to using Web Blocks? Web Blocks are independent too. Anything you can do to the iframe you could do to a container around the Web Blocks. Web Blocks can auto-refresh.

And Web Blocks can interact with the overall page, which pages in iframes can't.

Even worse, the session model *forces* pages to load in serial, making the page load slowly, while Web Blocks can be loaded with the "late load" pattern so that they come up as quickly as possible, or have the whole page display all at once if they load quickly.

There's no advantage (that I can see, but always open minded) to pages in iframes, and downsides.

J.Ja

The advantage is that you can include the page in an iframe that truly created dynamically. So you do not need to add every webblock to the page and hide/show containers. You can even include "pages" from eSpaces that aren't even referenced by your application as long as they are on the same domain (due to browser security not allowing cross domain iframes). This allows you to do things like add the same page multiple times (for example with different parameters)

We have used this approach to create a global dashboard which displays widgets from different applications based purely on entries in a "widget table" allowing us to dynamically add widgets without having to republish the dashboard every time.


Also iframes are not loaded sequentially, once the iframes are added they load in the background quite nicely.

John -

"The advantage is that you can include the page in an iframe that truly created dynamically. So you do not need to add every webblock to the page and hide/show containers."

I could do the same with the Web Blocks.

"You can even include "pages" from eSpaces that aren't even referenced by your application as long as they are on the same domain (due to browser security not allowing cross domain iframes)."

OK, you can do that, but what's the benefit to that? Why would I not be able to reference the Web Blocks?

"This allows you to do things like add the same page multiple times (for example with different parameters)"

You can do the same with Web Blocks.

"We have used this approach to create a global dashboard which displays widgets from different applications based purely on entries in a "widget table" allowing us to dynamically add widgets without having to republish the dashboard every time."

OK, I can see this being potentially useful in some circumstances, if you create a TON of dashboard widgets and push them out very quickly, but don't want to have to update the dashboard page itself. Depending on the project, this could be a pretty big benefit...

... but I could also get the same if I cheated and used RenderWebBlock().

Now... RenderWebBlock() is a cheat. (And I don't blame you for not being aware of it... the folks at OutSystems go out of their way to not advertise its existence!) But it works, and does everything that you are trying to do with the iframes, while making delivering the benefits of Web Blocks (specifically, the ability for the Web Blocks to interact with the page containing it).

J.Ja

""The advantage is that you can include the page in an iframe that truly created dynamically. So you do not need to add every webblock to the page and hide/show containers."

I could do the same with the Web Blocks."

In one of your posts you said 

"* Made a Static Entity representing the list of Widgets. It's not automatic to pull them, but it's a small item to maintain.

 * Made a block for "Widget". In the block is a bucnh of If's based on that WidgetId to display the correct Web Block. Nothing fancy/automated here, but again, it's a few moments of work and not a big deal.

"

 So you have to include every webblock at least once on your page and add the if's in. Even though it's not a lot of work with this method you don't have to do that at all as it's completely generated from the databasee.

""You can even include "pages" from eSpaces that aren't even referenced by your application as long as they are on the same domain (due to browser security not allowing cross domain iframes)."

OK, you can do that, but what's the benefit to that? Why would I not be able to reference the Web Blocks?"

Just makes it easier to avoid reference issues and having to republish the dashboard application every time you add new functions. Probably not that important for most people but we have a lot of applications and this helps with sideways reference issues

"... but I could also get the same if I cheated and used RenderWebBlock().

Now... RenderWebBlock() is a cheat. (And I don't blame you for not being aware of it... the folks at OutSystems go out of their way to not advertise its existence!) But it works, and does everything that you are trying to do with the iframes, while making delivering the benefits of Web Blocks (specifically, the ability for the Web Blocks to interact with the page containing it)."


Ok yes now that does sound very interesting and I will look into that. The main disadvantage with the way we are doping it is the potential licensing issues of cr4eating a lot more pages. If RenderWebBlock allows webblocks to be used in the same way that will be a far better solution.


Just for anyone interested in the iframe approach, below is the very simple javascript that is rendered from the expression, values are taken from a table containing the display widgets. The refresh parameter can be ignored, it is used by a simple component we created that creates a javascript refresh timer for the individual iframe.


" <iframe width='"+ListRecords1.List.Current.ReportItem.Width+"px' height='"+ListRecords1.List.Current.ReportItem.Height+"px' id='ifrm"+ListRecords1.List.Current.DashboardComponents.Id+"' src='"+GetEntryURL(ListRecords1.List.Current.ReportItem.PageName,ListRecords1.List.Current.Espace.Name,"Refresh",30000)+"' style="border:none;padding:0px;margin:0px"></iframe> "


Thanks John,  We actually did end up going the iframe route because of limitations and the massive inter dependency spider-web we ended up getting into when trying to use web blocks.  However 25+ iframes on 1 web page has problems as well with duplicate libraries being downloaded etc... but it does work and is quite a bit easier than web blocks from an implementation standpoint.  Thanks for adding to the conversation!