10 Replies Latest reply on Sep 7, 2009 5:44 PM by rickcr

    How come I can't do this - calling a component method from another. getting NPE

    rickcr Level 1

      This confuses me..

       

      I have two components. A navigation component with buttons like "add employee"

       

      If you click on on 'add employee' I want to initialize some fields on the "employeeForm" component. I can probalby do this making some of the items I want to modify bindable but shouldn't I be able to just do:

       

       

      //employeeForm..

      public function setUp():void {

          //later I'll have logic her for update vs add
          empPanel.title = "Update Employee";
          submitButton.label = "Update";

      }

       

      //other component event handler..

      private function handleEmployeeSelectedEvent(event:EmployeeSelectedEvent):void {
           empForm.employee = event.selectedEmployee;  //works fine

           empForm.setUp(); //problem the first time this is called
           showViewStackComponent('empForm'); //works fine

      }

      The call to empForm.setUp() will cause a Null pointer about not being able to set a null object - but only on the first hit. In other words, after acknowledging the error, subsequent calls to setUp work just fine, just not the first time.

       

      What am I doing wrong?

        • 1. Re: How come I can't do this - calling a component method from another. getting NPE
          sri harsha namala Level 2

          Hi,

           

                     May be Your Panel(empPanel) or Button(submitButton ) may not be Initialized Please check Once .

                    If not give what error its throwing.

          • 2. Re: How come I can't do this - calling a component method from another. getting NPE
            rickcr Level 1

            Sri harsha Namala wrote:

             

             

             

                       May be Your Panel(empPanel) or Button(submitButton ) may not be Initialized

             

            That is probably what's happening, but I'm confused then what is supposed to trigger those initializations? I'm actuallly making the call to even display that form (call to showViewStackComponent) before even calling the setup() function?

             

                 empForm.employee = event.selectedEmployee; 
                 showViewStackComponent('empForm');
                 empForm.setUp();

             

             

            If I comment out the calls to empPanel.title and submitButton.label the code does NOT throw the following error, so I do believe it's somehow related to those components not being initialized, but stuck on what to do about it?

             

            TypeError: Error #1009: Cannot access a property or method of a null object reference.
                at components::EmployeeForm/setUp()[/Users/rick/Documents/Flex Builder 3/Employee-Maintenance-Flex/src/components/EmployeeForm.mxml:28]
                at EmployeeMaint/handleEmployeeSelectedEvent()[/Users/rick/Documents/Flex Builder 3/Employee-Maintenance-Flex/src/EmployeeMaint.mxml:41]
                at flash.events::EventDispatcher/dispatchEventFunction()
                at flash.events::EventDispatcher/dispatchEvent()
                at mx.core::UIComponent/dispatchEvent()[C:\autobuild\galaga\frameworks\projects\framework\sr c\mx\core\UIComponent.as:9408]
                at components::MainNavigationComponent/addEmployeeClick()[/Users/rick/Documents/Flex Builder 3/Employee-Maintenance-Flex/src/components/MainNavigationComponent.mxml:24]
                at components::MainNavigationComponent/__addEmployeeButton_click()[/Users/rick/Documents/Fle x Builder 3/Employee-Maintenance-Flex/src/components/MainNavigationComponent.mxml:30]

            • 3. Re: How come I can't do this - calling a component method from another. getting NPE
              sri harsha namala Level 2

              Hi,

                     If you call ViewStack before then it should work Can u post Your Code?

              • 4. Re: How come I can't do this - calling a component method from another. getting NPE
                rickcr Level 1

                Sri harsha Namala wrote:

                 

                Hi,

                       If you call ViewStack before then it should work Can u post Your Code?

                 

                I, at least 'thought' I was doing that which you'll see in the following code. Thanks so much for looking at this. I'm pulling my hair out over this.

                 

                I can't figure out how to post code here so I posted the relevant pages here:

                 

                http://pastie.org/608568 EmployeeMaint.mxml (the main app page)
                http://pastie.org/608569 MainNavigation.mxml
                http://pastie.org/608576 EmployeeForm.mxml

                 

                The flow is you click on "add employee" on main navigation, fires the 'addEmployeeClick' function which dispatches to 'EmployeeSelectedEvent' which is handled by 'handleEmployeeSelectedEvent' on EmployeeMaint.mxl (this handler is where you see the call to show the view stack and to the setUp() call)

                 

                I also zipped up the small project in case that helps. You an download it here:

                 

                http://dl.getdropbox.com/u/86998/Employee-Maintenance-Flex.zip

                 

                (If you want the server side components to see it run as well I can provide them (Java).)

                 

                Thanks again for looking at this.

                • 5. Re: How come I can't do this - calling a component method from another. getting NPE
                  TheFlexGuy Level 2

                  Set creationPolicy="all" on the ViewStack component.  Then all the views will exist and you will be able to set variables on them even before they've been shown.  By default, they aren't created until they are shown.

                  <mx:ViewStack id="mainViewStack" width="100%" height="100%" creationPolicy="all">

                  • 6. Re: How come I can't do this - calling a component method from another. getting NPE
                    rickcr Level 1

                    Thanks FlexGuy! - That definitely sovled it (after I modified a few things .)

                     

                    The only slight issue was that on some of the components in my viewStack, I was using a creationCompletion event that called an init method to load some data from some remote services. This was a 'slight' issue since unless the user is authenticated I don't allow the remote calls. For now I'm getting around this by not making any creationComplete remote calls, but a better solution will be to not make my loginForm part of the mainpage view stack (I'll probably have my initial page just have a view stack of "login" and a view stack of the "main page" (where the main page would then have another view stack of the views I care about.)

                     

                    I'm curious though, is there a way to programatically do the intialization of a viewstack component? In other words, rather than define creationPolicy="all" on the ViewStack (which seems to initialize all of them), is there a way I can say "initialize this particular view stack"  when I want, THEN go ahead and set any variables on that view stack component. You'd think just trying to show the viewstack component first would be enough, but apparently it is not.

                     

                    Thanks again. (I wish I found this last night, I would have actually been able to enjoy my Sunday evening.)

                    • 7. Re: How come I can't do this - calling a component method from another. getting NPE
                      TheFlexGuy Level 2

                      Good question, I'd suggest making a new thread about it.

                      • 8. Re: How come I can't do this - calling a component method from another. getting NPE
                        rickcr Level 1

                        What's odd now is I'm running into similar problems when I decide to have more than one view stack (sort of nested) even though I give them both creationPolicy="all"

                         

                        For example I decided to set things up like..

                         

                        <mx:ViewStack id="initialViewStack" width="100%" height="100%" creationPolicy="all" >
                                <comp:LoginForm id="login"/>
                                <comp:Main id="main"  width="100%" height="100%"/>
                            </mx:ViewStack>

                         

                         

                        And then on the Main component:

                         

                        <mx:ViewStack id="mainViewStack" width="100%" height="100%" creationPolicy="all">
                                <mx:HBox id="home">
                                    <mx:Label id="homeLabel" text="The cool Employee Maintenance Application" styleName="labelStyle"/>
                                </mx:HBox>
                                <comp:Employees id="employees" />
                                <comp:EmployeeForm id="empForm" />
                            </mx:ViewStack>

                         

                        All of this has me really thinking I'm not following some best practices, so what is the correct way people handle things when they have buttons on other components that are supposed to trigger something on a different component?

                         

                        All I want to do is if someone clicks "add employee" is:

                         

                        - Load any departments for a combobox from a remote object call (preferably only done ONCE - yet have no idea how to set it up so it happens only once.)

                        - Initialize some labels that are appropriate (eg Add vs Update)

                         

                        All the example applications I see have the buttons on the same component so things appear much easier. What I'm wanting to do shouldn't be that difficult yet I'm running into all kinds of problems with things being initially null.

                        • 9. Re: How come I can't do this - calling a component method from another. getting NPE
                          TheFlexGuy Level 2

                          The best practice way to share data between components is to use a shared model approach.  I described it in this thread: http://forums.adobe.com/message/2228840#2228840 but to summarize here, you have a class that holds variables such as currently selected item, and then other components and classes reference that.  It makes it much easier to add components that need the same data or swap out components when you decide to go a different route.

                           

                          Once this concept is grasped, you'll find the quality of your coding will improve a lot.

                           

                          -Marty [ http://www.theflexguy.com ]

                          Helpful/Answered? Please mark it as such.

                          • 10. Re: How come I can't do this - calling a component method from another. getting NPE
                            rickcr Level 1

                            Sorry if this post gets long... Thanks FlexGuy, I looked at the link you provided, and I get the idea of what you are doing. In this case I have just one form that would be backed a single 'extra' model ( I say 'extra' because I still consider the model the class backing the form itself - eg Employee - not the extra flexish stuff like labels and titles, etc.) This extra model would then be used by by navigation component as well. I could start going down that route and for cases where data is shared between components it certainly makes sense.

                             

                            In my case though I'm still pretty stumped about something.... on a separate component that has navigation you click on an "Add Employee" button (or link) this needs to bring up the employeeForm which is a component of my view stack.

                             

                            Sincde I've added creationPolicy="all" like you mentioned I'm getting further along and I also decided to make some of the modifable items bindable:

                             

                            [Bindable] public var employee:Employee;
                            [Bindable] public var panelTitle:String;
                            [Bindable] public var submitLabel:String;

                             

                            Where I'm running into issues now is that the first time I access a comboBox that is backed by an ArrayCollection of Department objects I get the following error:

                             

                             

                            TypeError: Error #1009: Cannot access a property or method of a null object reference.
                                at mx.managers::FocusManager/focusInHandler()[C:\autobuild\galaga\frameworks\projects\framew ork\src\mx\managers\FocusManager.as:601]
                                at flash.display::Stage/set focus()
                                at mx.core::UIComponent/setFocus()[C:\autobuild\galaga\frameworks\projects\framework\src\mx\ core\UIComponent.as:6952]
                                at mx.controls::ComboBase/setFocus()[C:\autobuild\galaga\frameworks\projects\framework\src\m x\controls\ComboBase.as:1224]
                                at mx.managers::FocusManager/setFocus()[C:\autobuild\galaga\frameworks\projects\framework\sr c\mx\managers\FocusManager.as:553]
                                at mx.managers::FocusManager/mouseDownHandler()[C:\autobuild\galaga\frameworks\projects\fram ework\src\mx\managers\FocusManager.as:1896]

                             

                            However, after continuing the combox is fine and displays the items just fine and subsequent clicks on the departments combobox do not throw any errors - it's just this first time call.

                             

                            It's driving me nuts as to the reason why and the solution?

                             

                            My combobox looks like:

                             

                            <mx:FormItem label="Department">
                                 <mx:ComboBox id="departmentsID" prompt="Select a Department..."   labelField="name"  /> 
                            </mx:FormItem>

                             

                            And it's populated when I call setup() from my navigation component when the addEmployee button is clicked.

                             

                            //on employeeForm:

                            <mx:RemoteObject id="delegate" destination="flexDelegate" fault="faultHandler(event)">
                                     <mx:method name="getDepartments" result="resultGetDepartmentsSuccess(event)"/>
                            </mx:RemoteObject>

                             

                            public function setUp():void {
                                delegate.getDepartments();

                            }

                             

                            private function resultGetDepartmentsSuccess(event:ResultEvent):void { 
                                 var departments:ArrayCollection = event.result as ArrayCollection;
                                 departmentsID.dataProvider = departments;

                            }

                             

                             

                            (Eventually I want to get this collection only loaded once but I'll work on that later.)