SkunkSpinner
SkunkSpinner

Reputation: 11646

Weird ItemRenderer behavior

I have a really odd issue with an ItemRenderer. I have a main.mxml container with a ViewStack. When a user logs in, the initial view contains an AdvancedDataGrid--containing some data and the ItemRenderer below--which simply displays a Delete button. When the user logs in, this AdvancedDataGrid is automatically refreshed from the database. The Delete button should be enabled or disabled based on the user's role membership.

Scenario 1 (Logging in as an admin):

  1. Admin user logs in -- datagrid view is immediately displayed and Delete button is properly enabled for every row
  2. Logout
  3. Login as a non-admin user -- Data is refreshed and all of the rows are still enabled except for one. It could be the first, second or third rows--it's completely random. It's really wierd . . .

I restart my browser and follow scenario 2 . . .

Scenario 2 (Logging in as an non-admin):

INTERESTING FACT-- If I put a breakpoint in checkDeleteSecurity, it reaches it ONLY WHEN THE FIRST USER LOGS IN AND THE DATAGRID IS FIRST REFRESHED. When I logout and the next user logs in, the data grid is refreshed, but the checkDeleteSecurity breakpoint is never caught.

[Bindable]
private function checkDeleteSecurity ():Boolean
{
     return (SecurityProxy.CheckSecurity(SecurityProxy.UserName));
}

<mx:LinkButton label="Delete" click="onDeleteClick()" id="lbDelete" enabled="{checkDeleteSecurity()}"/>

Upvotes: 0

Views: 1186

Answers (2)

Christian Nunciato
Christian Nunciato

Reputation: 10409

It sounds like you might have a couple of things going on here. First, it's worth noting that ItemRenderers are re-used; in a grid (or list, etc.) containing, say, a list of ten album tracks, one row for each track, each row gets rendered properly when the list is initially created -- but when the underlying album, to extend the example, gets changed, the album-track renderers themselves will only respond automatically to the change if they're properly wired up to do so. Generally this involves overriding the setter of the data property of the renderer:

override public function set data(value:Object):void
{
    super.data = value;

    // .. Take some action
}

That's probably why your CheckSecurity method doesn't get called on data changes -- because the button's enabled property is the only way into it, and the button's already been rendered.

Also, binding to a function has its own issues. Someone actually asked this question last night, doing something quite similar to what you're doing (setting state on a button by binding to the result of a Boolean function):

Can I bind a Flex component property to a function?

Hope that helps! I'll keep an eye on the thread for follow-up comments if you have any.

Upvotes: 2

kenneth
kenneth

Reputation: 1065

what you should be doing is when your data is refreshed call lbDelete.enabled = checkDeleteSecurity(); This will make sure that the security function is called each time the data is refreshed.

I think that whats happening is your component is being created which calls the security function, but once its created then there is nothing to update the linkbutton.

Once an itemrender is created, say it generates 6 then when you refresh the data it will use those 6 itemrenders which are already created for the next set of data (but with updated data). If the next set of data needs 8 itemRenderers then it will only need to create another 2 renderers. So only those 2 itemrenders will call the security function as they haven't been created yet.

Upvotes: 0

Related Questions