9 Replies Latest reply on Oct 27, 2008 11:26 AM by ac361

    Help! Need to refresh image in datagrid row

    ac361 Level 1
      I have a Flex app that sends an image to a servlet which then resizes it and writes it to the disk. It also updates the database with the image name for that record. Then that row in the datagrid needs to change to show the new image uploaded to the server.

      Inside the set data() of the itemRenderer, this code seems to sometimes replace the image with the new one,

      outerDocument.myGrid.invalidateList();

      But 9 out of 10 times, it doesn't seem to work at all. After uploading, the image stays at the old one and doesn't get refreshed to be the new one. What am I doing wrong? Can you point me to some examples. Thank you.
        • 1. Re: Help! Need to refresh image in datagrid row
          ntsiii Level 3
          Is set data() being called when you expect it should?

          How are you updating the dataProvider?

          Tracy
          • 2. Help! Need to refresh image in datagrid row
            ac361 Level 1
            The propertiesXML variable gets populated by an XML file using an HTTPService call. In its RESULT handler, we call the useHttpService(), which uses values from the XML file.

            In turn, in the RESULT handler of the useHttpService(), we set the dataProvider of the grid, called dgPremiums (code below).

            As for the set data(), I'm not sure how to test to see when it's being called and when it needs to be called. Where should the call to the invalidateList() be? I've got it both inside the set data() and also in the UPLOAD_COMPLETE_DATA event handler of the file upload.

            I've spent three days on this and am no closer to an answer. Your help is much appreciated :)

            private function useHttpService():void {
            serviceGridReader.cancel();
            var date:Date = new Date();
            this.serviceGridReader.url = propertiesXML.property.(name=="ViewHandler").value + "?dt=" + date.toTimeString();
            serviceGridReader.resultFormat = "e4x";
            serviceGridReader.contentType = "application/xml"; // Must have this or will get IOError -- servlet generates XML document.
            serviceGridReader.method = "POST";
            serviceGridReader.addEventListener(ResultEvent.RESULT, httpViewHandlerResult);
            serviceGridReader.addEventListener(FaultEvent.FAULT, httpViewHandlerFault);
            serviceGridReader.send();
            }

            private function httpViewHandlerResult(event:ResultEvent):void {
            premiums = XML(event.result);
            this.dgPremiums.dataProvider = premiums.premium;
            }

            private function httpViewHandlerFault(event:FaultEvent):void {
            var errorMessage:ErrorMessage = event.message as ErrorMessage;
            Alert.show("rootCause: " + errorMessage.rootCause.toString());
            }
            • 3. Re: Help! Need to refresh image in datagrid row
              ntsiii Level 3
              If you are re-assigning the dataProvider, as you are, then you can be assured that set data() is being called on all renderers.

              This means the problem is "after"that.

              Use a trace() statement (in set data()) to write out the value of the property that contains the image url. make sure it is correct.

              Does your image item renderer store the item in an instance variable in set data(), then call invalidateProperties()?

              Then, in commitProperties() are you using that instace var to set the source of the image?

              Tracy
              • 4. Re: Help! Need to refresh image in datagrid row
                ac361 Level 1
                Hi, Tracy. Thank you for your continued help! It's very much appreciated; I've been stuck for so long on this problem, I saw no light at the end of the tunnel.

                In answer to your questions, here's what the code does and perhaps you can guide me as to where the invalidateProperties() and the commitProperties() need to be called:
                - The user clicks the Browse button in the row to select an image file.
                - Then s/he can click the Upload button. At this point, the file is sent to the Java servlet, which resizes it and stores it on the server, with the record's "Premium ID" being its filename. The Premium ID is an alphanumeric value, such as "ABCD123".
                - The server generates a small XML response, which Flex then reads in the UPLOAD_COMPLETE_DATA handler. This contains the filename, which is stored on the datagrid.selectedItem.FileName custom variable; this variable isn't part of the original dataprovider XML.
                - In the set data() of the image column, the code checks to see if that value exists; if so, it does an image.load() with the path + data.FileName. Else it sets the image's load() to the value from the dataprovider.

                After loading the image using data.FileName, the code calls the outerDocument.datagrid.invalidateList(). I also have a Refresh button that calls this. On some occasions, if I hit the Refresh button on the row enough times, it seems to get the new image in. The code also has calls to the outerDocument.datagrid.invalidateDisplayList() to no avail.

                How does the invalidateProperties() and commitProperties() fit into this? May you have a wonderful evening. Thanks for your help. Once I'm in the office on Monday, I can use the trace method. By the way, how do you see the trace statements? Do they come up in Flex Builder when the app is running? Sorry for the newbie questions.

                I'm eager to learn Flex because I see the potential for it for everybody who builds for the Web. For me, these are growing pains :)
                • 5. Re: Help! Need to refresh image in datagrid row
                  ac361 Level 1
                  Hi. I've tried using the invalidateProperties() and commitProperties() in the itemRenderer, but it's not working correctly. Here's the code for the column,

                  <mx:AdvancedDataGridColumn id="imageCol" headerText="Image Column" wordWrap="true">
                  <mx:itemRenderer>
                  <mx:Component>
                  <mx:VBox>
                  <mx:Script>
                  <![CDATA[
                  import mx.controls.Text;
                  import mx.events.FlexEvent;

                  private var fileName:String = "";
                  private var loaded:Boolean = false;

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

                  invalidateProperties();
                  dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));

                  if (data.FileName != undefined && data.FileName != null
                  && data.FileName != ""){
                  loaded = true;
                  fileName = data.FileName;
                  }
                  else if (getFilename(data) != null) {
                  loaded = true;
                  fileName = getFilename(data);
                  }
                  }

                  public function getFilename(item:Object):String {
                  if (item.image == undefined || item.image.filename == undefined) {
                  return null;
                  }
                  else {
                  return item.image.filename;
                  }
                  }

                  // Implement the commitProperties() method.
                  override protected function commitProperties():void {
                  super.commitProperties();

                  var path:String = " http://myserver.com/servlet/fpauto/uploads/";

                  photoLoad.load(path + fileName);
                  }

                  override protected function createChildren() : void {
                  super.createChildren();

                  if (loaded) {
                  photoLoad.visible = true;
                  photoBox.removeAllChildren();
                  }
                  else {
                  var text:Text = new Text();
                  text.text = "";
                  text.text = "No Photo Found";

                  photoBox.removeAllChildren();
                  photoBox.addChild(text);
                  photoLoad.visible = false;
                  }
                  }
                  ]]>
                  </mx:Script>
                  <mx:Image id="photoLoad" visible="false" autoLoad="false" />
                  <mx:HBox id="photoBox">
                  </mx:HBox></mx:VBox>
                  </mx:Component>
                  </mx:itemRenderer>
                  </mx:AdvancedDataGridColumn>
                  • 6. Re: Help! Need to refresh image in datagrid row
                    Level 7

                    "curious_Lee" <webforumsuser@macromedia.com> wrote in message
                    news:ge4g9u$f3n$1@forums.macromedia.com...
                    > Hi. I've tried using the invalidateProperties() and commitProperties() in
                    > the
                    > itemRenderer, but it's not working correctly. Here's the code for the
                    > column,

                    instead of using photoLoad.load(), have you considered setting
                    photoLoad.source = path+fileName?


                    • 7. Help! Need to refresh image in datagrid row
                      ac361 Level 1
                      I'd set the autoLoad="false" so at first it wasn't working. Let me test it and see what I get now that at least it shows some images on first load of the page.
                      • 8. Re: Help! Need to refresh image in datagrid row
                        Level 7

                        "curious_Lee" <webforumsuser@macromedia.com> wrote in message
                        news:ge4je0$j68$1@forums.macromedia.com...
                        >I tried that, but get no images displaying. Not sure why.

                        I'd put a breakpoint on the closing brace of commitProperties() and inspect
                        the properties of photoLoad. Might give you some insight.


                        • 9. Re: Help! Need to refresh image in datagrid row
                          ac361 Level 1
                          Finally found a solution:
                          - Changed the Java servlet to concatenate the time in milliseconds to the filename, ensuring it will be unique. Earlier, the filename for that record was the same as its ID; this increased the likelihood of caching.
                          - Modified the Flex app to refresh the dataProvider for the grid with each upload. Based on a tip by a blogger ( http://joelhooks.com/2008/02/07/flex-preventing-datagrid-scrolling-when-the-dataprovider-i s-updated/), I'm able to put the user back at the same record again after the refresh.