views:

90

answers:

1

Hi All

I have a DropdownList that shows a list of providers & the Provider associated with that Patient must be selected.

The Dropdown list:

<s:DropDownList id="providerList"
        width="80%"
        fontSize="12"
        fontWeight="bold"
        selectionColor="white"
        creationComplete="providerList_creationCompleteHandler(event)"
        dataProvider="{model.practiceProviderList.practiceProviders}"/>

where practiceProviders is an ArrayCollection

The CreationCompleteHandler function:

protected function providerList_creationCompleteHandler(event:FlexEvent):void
   {
    var firstN:String;
    var lastN:String;
    var providerObj:Provider = new Provider();

    if (model.patientDetails.patientDetail.patientProviders != null && model.patientDetails.patientDetail.patientProviders.length > 0)
    {
     firstN = patientDetailsModel.patientDetails.patientDetail.patientProviders.getItemAt(0).provider.providerName.firstName;
     lastN = patientDetailsModel.patientDetails.patientDetail.patientProviders.getItemAt(0).provider.providerName.lastName; 

for (var count:int = 0; count < patientDetailsModel.practiceProviderList.practiceProviders.length; ++count)
     {
 providerObj = patientDetailsModel.practiceProviderList.practiceProviders.getItemAt(count, 0).provider as Provider;

if (providerObj.providerName.firstName == firstN && providerObj.providerName.lastName == lastN)
      {
 this.providerList.selectedIndex = count;
      }
     }
    }
   }

The issue is when I go to this page the first time, the error is :

TypeError: Error #1009: Cannot access a property or method of a null object reference.
 at com.newwavetechnologies.modules::demographics/providerList_creationCompleteHandler()[C:\harish\flex\apps\workspace\dataCollection-flexUserInterface\src\com\newwavetechnologies\modules\demographics.mxml:166]
 at com.newwavetechnologies.modules::demographics/__providerList_creationComplete()[C:\harish\flex\apps\workspace\dataCollection-flexUserInterface\src\com\newwavetechnologies\modules\demographics.mxml:359]
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at mx.core::UIComponent/dispatchEvent()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\UIComponent.as:12266]
 at mx.core::UIComponent/set initialized()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\UIComponent.as:1577]
 at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:759]
 at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]

where line 166 is:

if (providerObj.providerName.firstName == firstN && providerObj.providerName.lastName == lastN)

The providerObj is null the first time. But when hit back and come to the same page again, everything works fine and 1 of the providers in the list is selected correctly.

Probably I think the first time, the creationComplete handler method is called before the List is populated. The 2nd time when the call is made, the list is populated and the handler works fine. It would be great if someone can help me in this regard on how to go about this.

Thanks

Harish

+2  A: 

It's hard to tell what's going on here, but the problem lies here:

providerObj = patientDetailsModel.practiceProviderList.practiceProviders.getItemAt(count, 0).provider as Provider;

There's a tonne of places in that line that Null pointer exceptions could occur.

Most likely - the practiceProvider returned at position count doesn't have a provider set. We can't see how this value is populated, but given this code works later, I'd say you've got a race condition happening - the data is being accessed before it's been set.

At very least, you should add a guardClause for this:

var practiceProviders:ArrayCollection = patientDetailsModel.practiceProviderList.practiceProviders;
for (var count:int = 0; count < practiceProviders.length; ++count)
{
      providerObj = practiceProviders.getItemAt(count, 0).provider as Provider;
      if (!providerObj)
         continue;
      // etc
}  

The race condition is a little trickier, given the asyncronous natoure of flex server calls. (I'm assuming that you're loading the data from a remote server).

There's two approaches to solve this - either

  • defer execution of this method until the data has loaded - you could do this by adding an eventListener to the ResultEvent of the RemoteService

or

  • Don't worry about it the first time around, but re-execute the method whenever the data changes.

eg:

protected function providerList_creationCompleteHandler(event:FlexEvent):void
{
     dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE,onCollectionChange,false,0,true);
    updateProviders();
    // Rest of existing creationComplete code moved to updateProviders();
 }
 private function updateProviders()
 {
       // Code from existing creationComplete handler goes here
 }
 private function onCollectionChange(event:CollectionEvent):void
 {
      updateProviders();
 }
Marty Pitt
Thanks Marty for your response, It got rid of the error. But no provider is selected the first time around. The next time it does. So still doesn't solve my issue :( Is there a way to resolve the race condition. Sorry but I'm new to the Flex world!
Harish
I've updated my answer with a possible solution.
Marty Pitt
Marty, thank you. I guess I found out what causes the error. The providerObj was not Bindable. So I added that and voila!. I'm going to mark your answer as right :). Thank you so much!!!
Harish