views:

747

answers:

2

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):

  • Non-admin user logs in -- datagrid view is immediately displayed and Delete button is properly disabled for every row
  • Logout
  • Login as a admin user -- All of the rows are still disabled except for one. It could be the first, second or third rows--it's completely random. Just the reverse of the first scenario.

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()}"/>
A: 

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.

kenneth
+2  A: 

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):

http://stackoverflow.com/questions/445313/can-i-bind-a-flex-component-property-to-a-function#445669

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

Christian Nunciato
That was my question . . . This was part 2 ;)
The data property setter will be called every time the item row is bound? That's interesting. So, if I have 10 rows of data in datagrid with a Delete button in an ItemRenderer. I pull new data and only get 3 rows. Even though rows 4-10 look empty, you're saying the Delete button is still rendered?
Overriding set data did it!
Awesome, good to hear. Yeah, I'm surprised it took me so long to learn that one myself; I've read several Flex books, and loads of docs, and for how useful it is to know, you'd think it'd be more prominently documented. Oh, well -- glad it helped!
Christian Nunciato