Writing a random list item widget

Topics: Customizing Orchard, Writing modules
Editor
Dec 7, 2011 at 4:03 AM

I would like to randomly show a content item from a list in the sidebar of my site. For example, I have a list of images and I would like to build off of the container widget to allow for options to only show 1 item and make it random. 

Can I copy the Container Widget and just trim it down to just pulling a random item? I can't seem to find the Container Widget code in modules so this makes me think it is in Core?

Coordinator
Dec 7, 2011 at 6:33 AM

It's defined in \src\Orchard.Web\Core\Containers\Migrations.cs. The relevant part you are probably looking for is the container part.

Editor
Dec 8, 2011 at 3:18 AM

So if I wanted to build my own widget called "Random Container Item Widget" would I just copy and trim down this code for the most part?

Editor
Dec 8, 2011 at 2:19 PM

Does it make sense to make a new content part called "Random Item Containers" and mimic everything except the data retrieval piece, or build a content part that can attach to the existing Container type and then do the filtering there?

Dec 8, 2011 at 2:51 PM

I would do the second one, if you're on 1.x, because then you can just hide the normal list with placement and render your own shape.

Editor
Dec 8, 2011 at 2:58 PM

Yes, I am on 1.3. 

So I am fairly new to module development. But would I add some logic in my module's placement.info to hide the normal rendering : <Place Parts_ContainerWidget="Nowhere"/>   ??

The rendering of my own shape, would that occur once my module was called in the request cycle after all the other content parts were called? I would get a list object and I could randomly return a single item?

Dec 8, 2011 at 10:05 PM

To hide shapes use <Place Parts_ContainerWidget="-"/> - that's the nowhere zone (otherwise the rendering code will still run even tho your item doesn't display). Use shape tracing to find out the name of the shape you want to target.

Drivers render shapes in whatever order Autofac provides the dependencies, but that doesn't really matter, because of course you control the final position with placement.

The important thing to realise is that in your driver you have to wrap the code in a delegate function like this:

return ShapeResult("Parts_RandomContainerItem",()=>{

    var item = part.(code to get your random item);

    return _contentManager.BuildDisplay(item,"Summary");

});

By doing things this way, your code will only run if Placement actually finds a zone for your shape. This means you can have many complex shapes available for a part but only incur the overhead for the ones you actually use in your display.

Dec 9, 2011 at 1:22 PM

Hello arock3,

I have been wanting to create a "randomizer" for Container items and am planning on working on it in the next week or so. I thought it would be really handy for Testimonials so they would pull through different every time. This has been a good discussion and I like what you and randompete concluded about using a new contentpart. That is the approach I will plan on taking. If I have success before you are finished I will post my code up here on this thread. Thanks for doing likewise and I will also keep watching this thread to see if others or you have success doing this.

Editor
Dec 9, 2011 at 1:44 PM

So in order to avoid writing a content part (due to time) I added a Parts.ContainerWidget.cshtml file to my Theme\Views folder. I then put the following code in there:

@using Orchard.ContentManagement;

@using Orchard.Core.Containers.Models;

@{   

IEnumerable<object> items = Model.ContentItems;   

Model.ContentItems.Classes.Add("content-items");   

Model.ContentItems.Classes.Add("list-items");   

var rand = new Random();

var zone = ???

}

@if(zone == "AsideSecond")

{

@Display(items.ElementAt(rand.Next(0, (items.Count() - 1))))

}

else

{

@Display(items)

}

------------

This will randomly display elements from the list. The only thing I would like to fix is the statement in front of it to check the zone before I call this. I am not sure how to grab the zone name in this context. I know a content part would be best, rather than filtering on the front end, but this is working now.

Dec 9, 2011 at 2:15 PM

Hello arock3,

The wrapper is not a bad idea, my only concern is that (normally) a widget for a container item only returns the Top 10 or the Top 20 (depending on your setting).  Therefore, if you exceed this many quantity in your List, I believe you would only be randomizing the display order of the Top "XX" and not the whole list. Either way, I think (from using Shape Tracing) that you can find the name at:

Model.Child.Parent.Content.ZoneName

I have not tested it but this is how it shows under Shape Tracing Model tab. Hope it works for you and I look forward to hearing whether your randomizer only works on the Top "XX" or whether it is truly randomizing the whole list.

Editor
Dec 9, 2011 at 2:43 PM

@jao28. Yea I set the count to return to something very large like 50 so this wouldn't happen to me. The statement Model.Child.Parent.Content.ZoneName does not seem to resolve in the Parts.ContainerWidget.cshtml. Ideally I could filter based on zone name or even widget name so that this filtering was not applied everywhere. Right now it works, since I am not using lists anywhere else. Know anyway to get the widget name?

Dec 9, 2011 at 3:19 PM

@arock3. Sorry, I was looking at a regular content item. According to Shape Tracing, it should be the following:

Model.Child.Parent.ContentItem.WidgetPart.Zone

HOWEVER, this is an easier way to get at it (and is the one I tested and found working):

Model.ContentItem.WidgetPart.Zone

Of course, this process should/will throw an error if no WidgetPart exists.  Therefore, you could first check to see if the WidgetPart exists before grabbing the Zone from it.  Of course, if your wrapper is for a widget it will :) so not likely worth checking. I decided to actually test this so here is my working code (based off your code of course):

@using Orchard.ContentManagement;
@using Orchard.Core.Containers.Models;

@{   
    IEnumerable<object> items = Model.ContentItems;   

    // Threw an error for me
    //Model.ContentItems.Classes.Add("content-items");   

    // Threw an error for me
    //Model.ContentItems.Classes.Add("list-items");   

    var rand = new Random();
    var zone = Model.ContentItem.WidgetPart.Zone;
}

@if(zone == "AsideSecond") {
    @Display(items.ElementAt(rand.Next(0, (items.Count() - 1))))
}

else {
    @Display(Model.Child)
}

Note that I had to use "@Display(Model.Child)" in the else statement as that is normally what get's rendered. Also, I only confirmed that the "zone" worked as expected (which is what you are really looking for). I don't have time right yet to confirm the "@Display(items.ElementAt(rand.Next(0, (items.Count() - 1))))" functions as you are expecting - I just don't have a list/container item in place to test it on. However, I look forward to hearing back from you if it does.

 

Editor
Dec 9, 2011 at 3:29 PM
Edited Dec 9, 2011 at 3:30 PM

@jao, Both of those statements do not return the zone name. The WidgetPart is null all of the time. I was thinking:

var zone = ((IContent) Model.ContentItem).As<ContainerWidgetPart>().Zone;

But it does not work either. Seems there is not much info at this point in the rendering.

Also the core template uses:

@Display(items);

Sooo I think it should be that.

My random rendering is working great....it is just if I ever add another container widget on the site, it will use this rendering too. Need something to switch on.

Dec 9, 2011 at 3:40 PM

@arock3, that is because I am overriding "Widget.Wrapper.cshtml" where it looks like you are overriding "Parts.ContainerWidget.cshtml". It is possible you are at too low of a level and thus you cannot get back up to the Widget level to access the actual zone information (which is on the WidgetPart).  The code I provided does work as "Widget.Wrapper.cshtml".  If you want to see what options you have, I HIGHLY recommend turning on the "Shape Tracing" module - it is a wonderful module that allows you to view the Model and all the options that go with it.

By the way, I fully understand why you want to just override the "Parts.ContainerWidget.cshtml" as that obviously gaurantees you are on a Container item. The alternative is to use my example and check to see if the widget CONTAINS a Container Part.  This way you get access to higher level information (such as the Zone).  Check the "Shape Tracing" first though as you might possibly have access to this...  Keep me informed and I will help as I can.

Editor
Dec 9, 2011 at 3:51 PM

Yea I mean I didn't think Widget.Wrapper was the right spot to do this, but you could filter the items at that higher level I guess.  Hmmm I am not sure. 

Yes, I use Shape Tracing a lot for this and am familiar with the module.

I think writing a content part would be the best solution obviously, I just am not proficient enough in writing them yet and needed a quick fix. It would be great to have an option in the container widget to randomize the item returned.

I think your solution would work if we did it in Widget.Wrapper.cshtml. I am going to investigate writing the content part this weekend.

Thanks for all your help! 

Dec 9, 2011 at 3:57 PM

I totally agree, a content type that can be added or removed at will and thus only target what you want is ideal.  Please keep me informed as you are working on it because I would like to contribute. I am a little bit away from being able to tackle it but it was on my list. I have not looked enough at what events a "Container" part has available to the developer, but if it had an "OnQuerying" event or something like that, this new content type that you are creating could catch that event and handle it and thus return the data (randomized of course). It could likely even grab the "Top XX" setting from the actual widget so you only return the number of results that the user was expecting to see.  It could be a great little content type - keep me informed.

Dec 9, 2011 at 5:54 PM

Since this is a topic on randomness, for obvious reasons I want to help :)

Firstly, you don't need to write a content part (I never said this) - all you need is a driver. That's one single code file, as opposed to a whole part, which requires many files including a driver.

The problem with the solution you've currently got is that Orchard is performing a whole lot of work just to display one item: "I set the count to return to something very large like 50". This means you are loading up to 50 items from the database, running them all through the whole rendering process (which isn't trivial) - only to use one of those resultant shapes.

This is why you need a driver - so you can have your own database code where you optimally read just a single item. By hiding the original Parts_ContainerWidget, you ensure it won't load any items from the database. In your custom random select query, you can ignore the list length anyway and just read the whole table.

Here's the tricky part. It's actually not so easy to do a random select query in MSSQL. 

See the following StackOverflow thread for reasons why

SELECT * FROM table ORDER BY RAND() LIMIT 1

and similar variants still have performance issues: http://stackoverflow.com/questions/19412/how-to-request-a-random-row-in-sql

The way I eventually found to do it was to create a database View that generates a random number, then join your table to it and sort on that number. Just been searching for a reference to this and I can't find it anywhere now. Still, unless you're querying 100,000s of rows performance should be better than the current approach. There are much better ways to, say, select approx. x% of rows; but it seems generally quite bad for seeking specific numbers.

Dec 9, 2011 at 6:20 PM

Hello @randompete, how could you help but join in - the name says it all :) Thanks for the reply and thanks for all your help on these forums, greatly appreciated.

Can you clear up some verbiage for me? When you say all you need is a driver, how would you create a driver and associate it with a Content Type if it were not wrapped up as a Content Part?  Maybe that would not be possible and you are saying just to hard code it (say by dropping the "driver.cs" it into the theme or something) instead of letting the user choose on what Content Type to apply this randomness.  Thanks for helping me learn on this one. 

And thanks for the great database references, I wonder if that can be done through NHibernate/LINQ... I was concerned about the difficulty of randomness and wanted to stay with native Orchard (i.e. without going into HQL or whatever that option is for typing straight SQL).  The only way I can think of would be to perform two queries. The first query would return a list of all the valid Content ID's back to the Driver. Then the driver (somehow) would have to extract a random set. Then (lot of assumptions here) that could be somehow inner joined with NHibernate.  If that was not feasible, then would somehow have to use "IN" as in SQL like "WHERE Id IN (XX, YY, ZZ)" - I am sure that would not be too speedy.

More than likely I did not use the correct terminology on some items above. Thanks for pointing this out (if you will) as I actively learning the product and want to be clear.

Editor
Dec 9, 2011 at 6:26 PM

My guess if create a Drivers folder in your theme. Then add a file named ContainerWidgetPartDriver.cs. This would then override the existing driver? But if we don't have our own content part to attach to our own content type that has the container part, how do we differentiate from normal rendering widgets and our RandomItemContainerWidget?

Dec 9, 2011 at 6:39 PM
Edited Dec 9, 2011 at 6:40 PM

All ContentPartDrivers across the whole of Orchard execute sequentially, and in the base implementation they check if their part type exists and run if so. This means that you can have multiple drivers for a single ContentPart.

This means you can just create your own:

public class RandomContainerWidgetContentPartDriver : ContentPartDriver<ContainerWidgetPart> {

 /// ... etc

}

It'll run as well as the core driver, and each will generate a shape result. But the construction delegates from each will only execute if Placement matches, so you just switch off Parts_ContainerWidget to stop it rendering or composing.

It also occurred to me once you have a proper random query, you can limit the query by the property ContainerWidgetPart.Record.PageSize - so it decides how many random items you want to show.

jao28: To clarify, I'm not talking about Content Types. A content type is kind of a template of which ContentParts to construct an item from, and settings to apply to those parts. Here I am talking about applying a driver to a single ContentPart (specifically the ContainerWidgetPart, but you could just as easily also do this with normal ContainerPart).

Whichever way is chosen, I think this will involve first executing an SQL statement (which you can do thru Orchard already) which retrieves just a randomised list of Ids. Then perform a ContentManager.GetMany(..) to properly load all the content items. There isn't a more efficient way to do it, due to the intricacies of content manager (although this might change with 1.4 / Projector).

I still think the method I previously used (joining/sorting on a random View) was actually much more efficient than the alternatives, for reasons which I dimly recall. The SQL to create the View looked like this:

 

CREATE VIEW [dbo].[RandomView]
AS
SELECT NEWID() As ID

GO

You can run that in a migration. You might want to use Orchard's table prefix to get a unique RandomView per tenant. Then finally compose an SQL to join the CommonPartRecords to it (filtering on CommonPartRecord.Container.Id) and sort on the RandomView.ID column.

 

When I originally found this technique I was dealing with a really large content database, and we had to do this to make things remotely efficient. We were doing things like pulling out randomised adverts, recommended content, etc., but from a very large pool, and from the same table as the rest of the content items.

Editor
Dec 9, 2011 at 7:54 PM

@jao, you getting all of this? Any thoughts on writing the driver? In my case there would be no more than 20 items at any time, so querying all the items and then filtering in the app is not a big deal to me. Just finding the right extension point is good enough for me.

 

Thanks so much for your insight RandomPete!

Dec 9, 2011 at 8:04 PM

You're not just querying them, you're rendering also. This takes a surprising amount of time because all the handlers/drivers have to be called all over again, it could easily slow your page down enough to feel it with just 20 items, especially if you had anything complex going on elsewhere on the page (and of course this does depend exactly what parts you have attached to your items). Still, it might not be so bad that you can't put up with it, but it'd be great to have a random content module available that could cope with larger amounts of content. e.g. for a "quote of the day" system where you had 1,000 quotes stored as content items - that kind of scenario would start causing serious performance issues.

Dec 9, 2011 at 8:12 PM

@randompete, first off, THANKS, I did not you could have multiple drivers sor a single Content Part - that rocks... there have been many times I have wondered how I could "override" an existing Content Part that someone created in their module but I did not want to hit their code (so that I could continue to use the future updates they made).  VERY powerful.  I am definitely going to work on a robust "Random Content" module - this could be very useful for the community as a whole. I have built a number of modules, but never hosted on CodePlex.  Time to get in the game - I will use all of these great ideas and start something and get it shared so many people can contribute.

@arock3, I am not sure I will be quick enough for your demands but I will try. As soon as I get something started I will post the link back here.

Editor
Dec 13, 2011 at 4:38 PM

If you hide the normal ContainerPart in placement.info and then create your own driver, won't it always use this driver in all cases a container widget is used? For example, on my homepage in the Contnet zone I have a list of items I need normal rendering, but then in the AsideSecond zone I want my container with a random image from a list to show up. Overriding Parts.ContainerWidget.cshtml in my theme I can access literally no information about what zone or widget title/id is being rendered. I would love to be able to switch off of widget name or ideally zone here. I know this is not ideal(all the reasons above) but I need a quick fix here. Here is my code:

@using Orchard.ContentManagement;

@using Orchard.Core.Containers.Models;

@{   

IEnumerable<object> items = Model.ContentItems;   

Model.ContentItems.Classes.Add("content-items");   

Model.ContentItems.Classes.Add("list-items");   

var rand = new Random();

}

@Display(items.ElementAt(rand.Next(0, (items.Count() - 1))))

 

I need someway to check zone here or at least widget name.

Editor
Dec 13, 2011 at 4:42 PM

Does the functionality described in this post http://orchard.codeplex.com/discussions/249947 now exist in the Widget Alternates module? Could I create a template called Parts.ContainerWidget-AsideSecond.cshtml

Doesn't seem to work

Coordinator
Dec 13, 2011 at 5:27 PM

Use shape tracing to find what alternates are available. When I do, I see the following for body part in tripel second zone:

~/Themes/TheThemeMachine/Views/Parts.Common.Body.cshtml
~/Themes/TheThemeMachine/Views/Parts.Common.Body-10.cshtml
~/Themes/TheThemeMachine/Views/Parts.Common.Body-HtmlWidget.cshtml
~/Themes/TheThemeMachine/Views/Parts.Common.Body-HtmlWidget-TripelSecond.cshtml
~/Themes/TheThemeMachine/Views/Parts.Common.Body-TripelSecond.cshtml

Dec 13, 2011 at 6:16 PM

Hello @bertrandleroy, @arock3, and @randompete:

As I am going through building this module, I am wondering what ability there is to have the Container Part NOT render WHEN it also has the new "Random Container Part" associated with it. For example, if I have a Content Type that contains both the Container Part and this new Random Container Part, I want my Random Container Part to handle the display while the existing Container Part would not even generate a shape (i.e. don't want to waste time generating a shape that won't be used).  I know in the Placement.info I can do this, but I was wondering if there is a way via code as I would rather my module control all of this instead of relying on the user to modify their placement.info every time. 

@bertrandleroy, I have read your  blog article on controlling Placement.info at http://weblogs.asp.net/bleroy/archive/2011/07/31/so-you-don-t-want-to-use-placement-info.aspx but it seems I would need to inject the helper into the user's active theme (along with some other things).  It seems that if I add my own Placement.info to my module that I could handle hiding the Container Part or Container Widget Part but this seems like this would trickle down across either the whole page or the current zone I elect to hide it in (as @arock3 is experiencing).  Ideally, I could return "false" in this part of the code telling all other ContentPartDriver<ContainerWidgetPart> not to render but then 1. I don't know if this is possible 2. How do I know my driver would run first:

public class RandomContainerWidgetContentPartDriver : ContentPartDriver<ContainerWidgetPart> {

/// ... etc

}

Obviously one solution is just to build a Random Container Widget Part that does all the functionality of the Container Widget Part but likely then I would have to deal with the issue of whether, in Orchard, this would be recognized as a true "Container Widget Part" such that containable items could be associated with it.  I would like to avoid this and modify as little of the native functionality as possible. 

Thanks again for any recommendations.

 

Editor
Dec 13, 2011 at 7:07 PM

It seems like to me that the "Randomness" should just be a content part that attaches to the normal container. It then will modify at the query level to only return 1 random item. (or a configurable amount of items). Then all the pagination, filtering, and sorting would come into play after that. It would just be an option that sits on the editor screen of the container widget.

Dec 13, 2011 at 7:33 PM

Hi @arock3,

I don't disagree, I just don't know how to prevent the existing Driver (i.e. the ContainerWidgetPart or even the ContainerPart) from rendering it's shape. We cannot have both shapes (i.e. the ContainerWidgetPart and the RandomContainerWidgetPart shapes) rendered otherwise you will have two shapes on screen...  It does not seem right to build a module that requires a user to override their own Placement.info either.  Thanks for your thoughts.

Coordinator
Dec 13, 2011 at 7:35 PM

@jao28: you should not attempt to override the user's placement decisions. I'm not sure why I would want you to suppress the rendering of the container part when your stuff is active. But if you really want to make different decisions than the regular container, I would advise creating a separate part. There is nothing magical about the regular container widget that you wouldn't be able to reproduce.

Coordinator
Dec 13, 2011 at 7:43 PM

So why does your widget content type have ContainerWidgetPart at all?

Dec 13, 2011 at 8:44 PM

Hello @bertrandleroy,

I may end up just creating a separate part. My concern was that, when in Orchard, for a Containable item to be used it has to be paired up with a "Container" part.  So, I was not sure my "RandomContainerPart" would be eligible for this functionality. In other words, is the "Container" part special because it implements a certain interface or because of something like the actual name "Container".  If it is because of something like the name then I cannot simply create a RandomContainerPart and expect it to work with the existing "ContainablePart".  However, it seems from what you have written that this should not be a concern and that I should be able to pair my new "RandomContainerPart" up with "Containable" parts and get the effect I want - time will tell.  I jsut did not want to reinvent the wheel if I could simply extend existing functionality.  However, sometimes it is quicker to just reinvent (in this case modify). Thanks for any additional comments you have and if you don't that is fine.  Thanks again.

Coordinator
Dec 13, 2011 at 9:01 PM

Also, your part does not necessarily need to render anything, if all it does is modify the data that other parts are displaying.

Dec 13, 2011 at 9:09 PM

Yeah, but there is no event (that I know of) to intercept the existing ContainerPart driver and deliver different data...  That is my goal is to simply override the data request and use the "native" containerpart but I would have to deal with one of the two problems:

  1. I need to override the existing part data retrieval process such that my data is used
  2. OR I need to have my driver used and prevent the existing driver from being processed

Without replacing the complete module, is there anyway to get around either one of the two items above?

 

 

 

Dec 13, 2011 at 9:12 PM

I don't think there's any way to hook into ContainerPart and modify the data that's displayed (especially since you only want it to display the random item in certain circumstances), I think the shape method is the best, if you want to leverage containers. It's not hard for a user to switch shapes on or off in placement, have your shape not displayed by default so they still get the normal container placement, and can switch the random item version on for specific content types and display types.

*However* there's a completely different (and probably easier) way you can go about this.

Rather than using a container, just create a whole new content type for this behaviour, and a new widget. I'll call this content type "RandomItem" for example. Then in your widget just do a content query for "RandomItem" content type and pick a random one to display it. Then any new "RandomItem" you create will automatically be in the random pool (and they can still interact with other containers if required). I think this is simpler, and I did a similar thing for Ad selection in a site I built ...

Coordinator
Dec 13, 2011 at 9:14 PM

You can have more than one driver for a part. Problem with handling shapes is that the data is already there. To properly implement that, you'd need to randomize at the level of the database request: if you do it on the shape, that would mean that you already queried the database for everything and randomize afterwards, which would be quite terrible.

The completely separate widget approach seems like the sane thing to do.

Editor
Dec 13, 2011 at 9:20 PM
How does the custom field filtering do it? It really is just another filter right? That happens at the db level too?

Sent from my iPhone so message may be brief.

On Dec 13, 2011, at 4:14 PM, "bertrandleroy" <notifications@codeplex.com> wrote:

From: bertrandleroy

You can have more than one driver for a part. Problem with handling shapes is that the data is already there. To properly implement that, you'd need to randomize at the level of the database request: if you do it on the shape, that would mean that you already queried the database for everything and randomize afterwards, which would be quite terrible.

The completely separate widget approach seems like the sane thing to do.

Dec 13, 2011 at 9:26 PM

If you hide the original shape with placement, the database work is never done (because the shape implements the factory method) and therefore you can provide your own shape with your own data, but based on the existing part.

Dec 13, 2011 at 9:38 PM

At a minimum, I have learned a lot just by having this conversation (and likely others who review this in the future will benefit also).  I am going to target a dedicated (separate) widget.

The next big thing will be to see if I can push the randomization down to the database level. @randompete you have some good ideas on that and I will be trying them (using the View approach). The current process I have requires that I pull a list of unique Id's (first database call) and then randomize the id's in order to select the final content I need (second database call).  This is fine on small datasets but will baloon as soon as the amount of content increases.  I will let you know... 

Oh yeah, @arock3, I have never succeeded with the "Custom Field Filtering" - I am not sure they are tied off. I bet @bertrandleroy or @randompete will have a better reply though...

Dec 13, 2011 at 11:54 PM

Hello Again @arock3,

I do believe @bertrandleroy has added value to Custom field filtering in his Vandelay Industries module. I have not tested it yet but as soon as I saw "Custom One", "Custom Two", and "Custom Three" options as a result of activating this module I immediately thought of your question in regards to custom field filtering. Thanks @bertrandleroy for adding even more value.

Coordinator
Dec 13, 2011 at 11:55 PM

It wasn't me :) The three custom fields come with the list feature iirc.

Editor
Dec 14, 2011 at 1:37 PM

@bertandleroy "So why does your widget content type have ContainerWidgetPart at all?"

I figured it needed the functionality from container to hold and edit all of the items a user might add to a list.

I guess your right though, it really can be its own separate piece of functionality. In my example, I have random quotes appear on each page of the site. These quotes are organized as a List>Quotes (Created Content Type in Orchard Admin). Basically, in summary view I wanted to only show 1 item and have it random. I added a container widget to my "default" layer and are controlling what appears through the view. (Got this working now and all is good. Even though it is pretty hacky.)

If you look at it again, it really could be a new widget type that just returns a random item of content of a specific type. RandomContentWidget, could just ask you to select the content type you want to randomize and then pull a random item from the DB without even caring about a container at all. This may be easier for me to write as it is a much simpler concept than a content part to container type, etc, etc.

I will try this approach out. Thanks Bertrand.