Re: [flexcoders] Re: Observing collections
Thanks guys. Can someone explain how ac:Observe (which this is based on) works? i.e. what triggers the handler call when somethng in the middle of the source binding expression changes (eg. b in {a.b.c.myCollection}? I don't see any event handlers, and there's a mysterious execute() method in the parent class (Observer). And would your version below also fire when b changes? Otherwise, Josh's example works too, but the collection event is the only trigger. On Thu, Aug 14, 2008 at 12:12 AM, Dennis van Nooij [EMAIL PROTECTED]wrote: try this: package com.adobe.ac { import mx.events.CollectionEvent; import mx.collections.ArrayCollection; import flash.events.Event; import mx.core.Application; import mx.core.UIComponent; /** * * monitors Collections and react on reassining of the variable * and changes in the collection which are bindable * */ public class ObserveCollection extends Observer { private var _handler : Function; private var _source : Object; override public function get handler() : Function { return _handler; } public function set handler( value : Function ) : void { _handler = value; if( value != null ) { isHandlerInitialized = true; if( isHandlerInitialized isSourceInitialized ) { callHandler(); } } } override public function get source() : Object { return _source; } public function set source( value : Object ) : void { if (_source != null){ _source.removeEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChangeHandler); } _source = value; _source.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChangeHandler); isSourceInitialized = true; if( isHandlerInitialized isSourceInitialized ) { callHandler(); } } protected override function callHandler() : void { try { handler.call( null, source ); } catch( e : Error ) { delay( e ); } } protected override function delay( e : Error ) : void { UIComponent( Application.application ).callLater( throwException, [ e ] ); } private function throwException( e : Error ) : void { throw e; } private function collectionChangeHandler (event:Event) : void { callHandler(); } } } cheers, Dennis --- In flexcoders@yahoogroups.com flexcoders%40yahoogroups.com, Alex Harui [EMAIL PROTECTED] wrote: Never used Observe, but if it implements IMXMLObject or you subclass and do so, then you can use it in MXML From: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com [mailto: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com] On Behalf Of Richard Rodseth Sent: Wednesday, August 13, 2008 4:16 PM To: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com Subject: [flexcoders] Observing collections For some reason I have an aversion to adding event listeners in ActionScript, favouring binding expressions and the Observe tag from Adobe Consulting. Not sure how rational this is, but there you have it. Binding is just so damn elegant. However, collections are a problem. It seems that so often you want to update something if either the collection itself or its contents changes, and you don't really care about the details of the change. I suppose if you're a DataGrid watching its dataprovider you do care and can minimize updates, but in many of the use cases I've encountered, that's not the case - my observer is going to do something with the whole collection (or maybe I've just been lazy about exploiting possible optimizations). Is there anything like the Observe tag that can be instantiated in MXML and can trigger a function call on a COLLECTION_CHANGE event?
Re: [flexcoders] Re: Observing collections
Oh, I just stepped through Observe, and I guess the standard binding mechanism calls the source setter again, which calls the handler. On Thu, Aug 14, 2008 at 6:49 AM, Richard Rodseth [EMAIL PROTECTED] wrote: Thanks guys. Can someone explain how ac:Observe (which this is based on) works? i.e. what triggers the handler call when somethng in the middle of the source binding expression changes (eg. b in {a.b.c.myCollection}? I don't see any event handlers, and there's a mysterious execute() method in the parent class (Observer). And would your version below also fire when b changes? Otherwise, Josh's example works too, but the collection event is the only trigger. On Thu, Aug 14, 2008 at 12:12 AM, Dennis van Nooij [EMAIL PROTECTED]wrote: try this: package com.adobe.ac { import mx.events.CollectionEvent; import mx.collections.ArrayCollection; import flash.events.Event; import mx.core.Application; import mx.core.UIComponent; /** * * monitors Collections and react on reassining of the variable * and changes in the collection which are bindable * */ public class ObserveCollection extends Observer { private var _handler : Function; private var _source : Object; override public function get handler() : Function { return _handler; } public function set handler( value : Function ) : void { _handler = value; if( value != null ) { isHandlerInitialized = true; if( isHandlerInitialized isSourceInitialized ) { callHandler(); } } } override public function get source() : Object { return _source; } public function set source( value : Object ) : void { if (_source != null){ _source.removeEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChangeHandler); } _source = value; _source.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChangeHandler); isSourceInitialized = true; if( isHandlerInitialized isSourceInitialized ) { callHandler(); } } protected override function callHandler() : void { try { handler.call( null, source ); } catch( e : Error ) { delay( e ); } } protected override function delay( e : Error ) : void { UIComponent( Application.application ).callLater( throwException, [ e ] ); } private function throwException( e : Error ) : void { throw e; } private function collectionChangeHandler (event:Event) : void { callHandler(); } } } cheers, Dennis --- In flexcoders@yahoogroups.com flexcoders%40yahoogroups.com, Alex Harui [EMAIL PROTECTED] wrote: Never used Observe, but if it implements IMXMLObject or you subclass and do so, then you can use it in MXML From: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com[mailto: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com] On Behalf Of Richard Rodseth Sent: Wednesday, August 13, 2008 4:16 PM To: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com Subject: [flexcoders] Observing collections For some reason I have an aversion to adding event listeners in ActionScript, favouring binding expressions and the Observe tag from Adobe Consulting. Not sure how rational this is, but there you have it. Binding is just so damn elegant. However, collections are a problem. It seems that so often you want to update something if either the collection itself or its contents changes, and you don't really care about the details of the change. I suppose if you're a DataGrid watching its dataprovider you do care and can minimize updates, but in many of the use cases I've encountered, that's not the case - my observer is going to do something with the whole collection (or maybe I've just been lazy about exploiting possible optimizations). Is there anything like the Observe tag that can be instantiated in MXML and can trigger a function call on a COLLECTION_CHANGE event?
Re: [flexcoders] Re: Observing collections
should all be based on property change events, the heart of binding On Thu, Aug 14, 2008 at 8:55 AM, Richard Rodseth [EMAIL PROTECTED] wrote: Oh, I just stepped through Observe, and I guess the standard binding mechanism calls the source setter again, which calls the handler. On Thu, Aug 14, 2008 at 6:49 AM, Richard Rodseth [EMAIL PROTECTED]wrote: Thanks guys. Can someone explain how ac:Observe (which this is based on) works? i.e. what triggers the handler call when somethng in the middle of the source binding expression changes (eg. b in {a.b.c.myCollection}? I don't see any event handlers, and there's a mysterious execute() method in the parent class (Observer). And would your version below also fire when b changes? Otherwise, Josh's example works too, but the collection event is the only trigger. On Thu, Aug 14, 2008 at 12:12 AM, Dennis van Nooij [EMAIL PROTECTED]wrote: try this: package com.adobe.ac { import mx.events.CollectionEvent; import mx.collections.ArrayCollection; import flash.events.Event; import mx.core.Application; import mx.core.UIComponent; /** * * monitors Collections and react on reassining of the variable * and changes in the collection which are bindable * */ public class ObserveCollection extends Observer { private var _handler : Function; private var _source : Object; override public function get handler() : Function { return _handler; } public function set handler( value : Function ) : void { _handler = value; if( value != null ) { isHandlerInitialized = true; if( isHandlerInitialized isSourceInitialized ) { callHandler(); } } } override public function get source() : Object { return _source; } public function set source( value : Object ) : void { if (_source != null){ _source.removeEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChangeHandler); } _source = value; _source.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChangeHandler); isSourceInitialized = true; if( isHandlerInitialized isSourceInitialized ) { callHandler(); } } protected override function callHandler() : void { try { handler.call( null, source ); } catch( e : Error ) { delay( e ); } } protected override function delay( e : Error ) : void { UIComponent( Application.application ).callLater( throwException, [ e ] ); } private function throwException( e : Error ) : void { throw e; } private function collectionChangeHandler (event:Event) : void { callHandler(); } } } cheers, Dennis --- In flexcoders@yahoogroups.com flexcoders%40yahoogroups.com, Alex Harui [EMAIL PROTECTED] wrote: Never used Observe, but if it implements IMXMLObject or you subclass and do so, then you can use it in MXML From: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com[mailto: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com] On Behalf Of Richard Rodseth Sent: Wednesday, August 13, 2008 4:16 PM To: flexcoders@yahoogroups.com flexcoders%40yahoogroups.com Subject: [flexcoders] Observing collections For some reason I have an aversion to adding event listeners in ActionScript, favouring binding expressions and the Observe tag from Adobe Consulting. Not sure how rational this is, but there you have it. Binding is just so damn elegant. However, collections are a problem. It seems that so often you want to update something if either the collection itself or its contents changes, and you don't really care about the details of the change. I suppose if you're a DataGrid watching its dataprovider you do care and can minimize updates, but in many of the use cases I've encountered, that's not the case - my observer is going to do something with the whole collection (or maybe I've just been lazy about exploiting possible optimizations). Is there anything like the Observe tag that can be instantiated in MXML and can trigger a function call on a COLLECTION_CHANGE event?
Re: [flexcoders] Re: Observing collections
To repeat what someone said earlier, this exact issue is already addressed quite cleanly by the aforementioned Observe tag (and it's more advanced version ObserveValue). I think the Observe/ObserveValue tags are easily useful enough that their inclusion in BindingUtils (or wherever mx:Binding is kept) would be an excellent update to the Flex SDK. Troy.
Re: [flexcoders] Re: Observing collections
Not sure I understand what you're responding to. I agree about the usefulness of the tags. I don't believe either of them would call a function when the contents of a collection changes (as opposed to the collection itself). The modification Dennis offered would. On Thu, Aug 14, 2008 at 10:37 AM, Troy Gilbert [EMAIL PROTECTED]wrote: To repeat what someone said earlier, this exact issue is already addressed quite cleanly by the aforementioned Observe tag (and it's more advanced version ObserveValue). I think the Observe/ObserveValue tags are easily useful enough that their inclusion in BindingUtils (or wherever mx:Binding is kept) would be an excellent update to the Flex SDK. Troy.
Re: [flexcoders] Re: Observing collections
I don't believe either of them would call a function when the contents of a collection changes (as opposed to the collection itself). The modification Dennis offered would. Sorry, completely missed the point, didn't I? ;-) You're right, what you're looking for would be useful as well! ;-) I'll have to take a look at Dennis' code. Troy.
Re: [flexcoders] Re: Observing collections
No problem. I'm glad someone else thinks it might be useful. I could even imagine a variation that had multiple handlers, or passed the event to the handler. I'm fascinated by what makes sense declaratively, and what doesn't. Flex is a great playground for the two styles. On Thu, Aug 14, 2008 at 10:51 AM, Troy Gilbert [EMAIL PROTECTED]wrote: I don't believe either of them would call a function when the contents of a collection changes (as opposed to the collection itself). The modification Dennis offered would. Sorry, completely missed the point, didn't I? ;-) You're right, what you're looking for would be useful as well! ;-) I'll have to take a look at Dennis' code. Troy.
Re: [flexcoders] Re: Observing collections
I'm fascinated by what makes sense declaratively, and what doesn't. Flex is a great playground for the two styles. That's exactly why I (and likely you) found the AS3-based event handler method distasteful (from your original post): you're forced to do something best expressed declaratively in the imperative language. I'd like to see Flex become even stricter in this distinction: - MXML is declarative and best represents *structure*. - AS3 is imperative and best represents *behavior*. - CSS best represents *styling*. The closer we can get to not being forced to muddy the 3 the better our code will be. This thread touches on a big place where I often have to muddy MXML and AS3 (view elements reacting to nested and/or complex model changes). While I'm on the subject (though it's unrelated to this thread), I'd love to see Flex really beef up the CSS, allowing for things like applying multiple styles to a single component (e.g. style=redBox bigFont instead of just styleName=redBoxWithBigFont), style shorthands (e.g. padding: 1 2 3 4 instead of paddingTop: 1 paddingRight: 2, etc...), and making more layout properties stylable (width, height, x, y, left, right, etc.). Troy.
Re: [flexcoders] Re: Observing collections
As far as I recall mx:Binding just invokes a setter (for the destination property) and I'm pretty sure it doesn't watch CollectionChanged either. On Wed, Aug 13, 2008 at 8:42 PM, Amy [EMAIL PROTECTED] wrote: --- In flexcoders@yahoogroups.com flexcoders%40yahoogroups.com, Richard Rodseth [EMAIL PROTECTED] wrote: A little more context. I'm working on a view that builds itself dynamically (adding children to various containers) based on a description. So suppose my view has a property called description which has a property things that is the collection or array. It's no great hardship to add a listener in the setter for description, but I wish I could say something like: mx:WatchCollection source={description.things} handler=thingsChanged/ Have you tried the Binding tag? The first time I ever saw it in action was in this file: http://examples.adobe.com/flex2/inproduct/sdk/photoviewer/PhotoViewer. html HTH; Amy