Easy way to tell if data is dirty - apache-flex

I am currently using databinding on a group of spark form elements and want to know if the data class I am bound to is dirty.
It might be nice if spark "Form" elements would trigger a change event that bubbled up to and was caught by a spark "Form". Then I could just add an event listener to the form. But I don't see something like that.
So besides comparing a copy of the original data class to the bound data class OR adding a change event to each form element and capturing that event, what's an easy way of knowing a class object has changed?

Make an extension of TextInput or whatever other input elements you'll have in your form then in your components creation complete register a listener for the change event, in the handler dispatch a bubbling event, then in your document that contains the form use your custom elements and add a listener via AS3 to the Form for the event you dispatched and stop it's propagation at that point.
Otherwise I think your second solution of change handler on each wouldn't be too bad. If you have a lot of elements in the form or it's dynamic you could write a function that steps through the form items of the form and checks their children then you just have to write a switch that deals with each class type (you can use http://www.actionscriptdeveloper.co.uk/getting-the-class-of-an-object-in-as3/on each of the child elements to determine what type it is, then if it's a TextInput or whatever register the appropriate event to call your commonly used function, just be sure it has a generic Event as it's parameter since all other Events will be sub-classes thereof).
So far as I know there is no easy way to listen for changes to the underlying data from the ArrayCollection or other wrapper ListCollectionView data structures. Part of the problem is the elements added a collection aren't required to implement any sort of interface to allow for listeners to be registered. That is, the data elements aren't necessarily event dispatchers, the only other way for this information to be communicated to the List would be if the data elements had a handle on all lists that contain that element and they mark something on the lists to indicate "dirty" when any property is set. These are all achievable within the constraints of the language but aren't provided out of the box as the usage for them is probably limited and could potentially unnecessarily bloat the cpu usage of the ListCollectionView in other cases.

Related

What is the principle of ractivejs's two way binding?

I'm using ractivejs,I know angularjs's two way binding based "dirty check",but I don't know the principle of ractivejs,who knows?I want a detailed answer.
Ractive doesn't diff or check anything, it uses the declarative template to know exactly what needs to be updated.
Ractive constructs a virtualDOM based on the template. The templated portions of the virtual dom (things with {{...}} in them) register with the viewmodel using the keypaths they contain.
When a ractive.set(...) or one of the other data manipulation methods occurs, dependents are notified of the change (computations and expressions, upstream and downstream keypaths, as well as observers are also notified).
Ractive uses a runloop that batches the actual DOM changes for any set operation to occur at the end of the cycle.
In addition to API calls, Ractive offers twoway binding by default. This maps needed DOM events from form input controls to the API calls to set the data to which it is bound (via the specified keypath).
Ractive does offer the .update(keypath) and .updateModel(keypath) methods which can be used to flush changes from model to view, or view to model when it is not possible for Ractive to know about them, for example using a third-party widget library.

Flex data binding re-bind when data model not change, possible?

There is a common case that I bind a data model value to a GUI control, say, a TextInput. The data model is retrieve from backend.
If user change the value of the TextInput, then click refresh button to retrieve the data model from backend again, the GUI value will not change back. Re-binding not happen, Since the value of data model not changed, no propertyChanged event fired.
In this case, I must Programmatically set the model value to the GUI after data refreshing done.
I know bi-directional binding can solve this problem(when user change value on GUI, set the new value to data model immediately). But sometimes I cannot use bi-directional binding, for example, the data model is a int, but user input a non-int value, I cannot set the value to data model. So the value in data model do not change, when refresh data, rebinding still not happen.
This will make the data binding useless. How to resolve this?
I put pseudo-code here for now, I will put real code later:
1. retrieve a data model from server, via blazeds or something else.
2. bind the model to a TextInput on GUI.
3. user change the TextInput text.
4. User click a refresh button, triger retrieve the model value again.
5. Now since the model value do not change, no PropertyChanged event fired.
6. GUI value still is the user's input, not the value from the model.
I can clear the model value before set the velue back, make re-binding happen.(but sometimes you do not know how to clean the model value, take int for example, you may do not know the original value and happen set the same value). Or I can manually set the model value to GUI. But both are not good looking.
bi-directional binding not work since if user input a invalid value, I cannot set it to the model. Model value do not change, re-bind will not happen.
Bidirectional binding can be achieved in a variety of ways, not necessarily with the #-symbol. In your particular case you need to use the Binding-tag:
<fx:Binding source="parseInt(someNumberInput.text)"
destination="someModel.someNumberValue"/>
<s:TextInput id="someNumberInput" text="{someModel.someNumberValue}"/>
It's very important not to forget to parseInt() the numeric value.
You can dispatch binding events whenever you want. One way is to simply dispatch a PropertyChangeEvent on all properties you want to update, but another is to add your own binding event in addition to standard binding.
For instance, I think this will work:
[Bindable]
[Bindable (event="allChanged")]//make sure to dispatch this yourself when everything changes
public var myInt:int;
There is a possibility that the custom binding event might prevent Flex from generating the code in the background that does standard binding (I have never done the above, because if I am going to use custom events, I tend to not use the standard binding).
Flash Builder 4.5 has awesome code generation, so you can just convert a public variable to a getter and setter, and it will ask you if you want to fire a custom event for the property. If you check that box, it will write the code for you. Then you add the second metadata tag by hand.
The getter/setter method will perform better, because then each property will have its own event, rather than all of them firing on propertyChange and checking if the property is the correct one. But the other one is less verbose and more maintainable, if it works.
Use a relevant editor to edit a numeric value. Flex can not guess what you want to do.

How Do I See All Events Fired by an Object?

I am having trouble wiring up an event listener to a fl.transitions.Transition.
Is it possible to somehow view all the events an object fires? That way I could check I am using the correct event (and possible view better ones to use).
The easiest is to override the dispatchEvent method in classes where you want to intercept events.
You can find the classes in %CS_ROOT%\Common\First Run\Classes\mx\transitions\easing\.
You can also create a subclass of EventDispatcher with a custom dispatchEvent-implementation and use that as a subclass for all classes where you'll be wanting to intercept events.
greetz
back2dos
The problem is, you have to have an event type to listen for. The only way to do this is to add listeners for all the possible events.
Now, you can add a handler with an indeterminate event type, such as:
private function myUniversalHandler(event:*) : void {
trace(event.type);
trace(event.constructor.toString());
}
And this will report any event passed to it. Nevertheless, it simply won't be called unless it is listening for an event of a particular type. And adding all those listeners is a lot of work to go through. Better to study the events available to you from whatever class you are dispatching the vent from.
I would look at TransitionManager, and the events allTransitionsOutDone and allTransitionsInDone which it dispatches. I haven't used these, but my understanding of their function matches what you seem to be looking for.
checkout the online reference, you should see there all events (and inherited events) of a Class.
On a side note if you are using flex you might be using mx.states.Transition
There is no way, at runtime, to find out all the events that fire from a component. You'll have to explore the component source code to get a complete list.
Reviewing the ASDocs, as others have suggested, is a good way to get a handle on the documented events of a component; and in most cases you'll be able to find one to suit your needs.
You cannot programmatically get a list of all events fired by any given object. You can however get a list of all events fired by a standard library object (that are part of it's public interface) from its documentation (cilck on the show inherited events link) and decide whether you're using the appropriate one.
I have scratched my head quite a bit on this issue as well.
The answer is this
you can get a list of all event listeners that an object is listening to only if attached though MXML
if not attached through MXML you cannot see the events an object is listening to (attached by AS)
if you want to see all the events an object is listening to you can check for hasEventListener although this is a long coding way
another efficient way (if you can use it, I couldn't) is to monkey patch the framework and create a dictionary of listeners for every object.
you can accomplish that by patching FlexSprite and overriding the addEventListener function.
you should keep in mind, this will not work when you are loading the framework through RSL.

Equivalent of describeType for Flex Component EVENTS

Using "introspection" In Flex I can say:
var classInfo:XML=describeType(SomeObject);
Which will list for me the Accessors, Methods And Variables.
(http://livedocs.adobe.com/flex/3/html/help.html?content=usingas_8.html)
But what is the equivalent to programmatically inspect all of an object's possible EVENTS?
(NOT JUST the events for which event listeners have been set, but to somehow step through a list of all VALID EVENTS for which event listeners may POTENTIALLY be set -- I realize that such lists are readily available online, and that's great for cases when I know the object's type at design type, but I require some way to inspect any given displayobject programmatically at runtime, and determine what events, if any, are or may be associated with it.)
There isn't a way.
The Event information defined using the event metadata tag is done only for the purposes of code hinting and documentation via ASDocs. It has no relevance to events that the component may or may not be firing.
At any point in time, a portion of code can call "dispatchEvent" and dispatch that event. This is used very commonly for "somePropertyChanged" events which are used for bindings. These events rarely, if ever, get documented using the event metadata. But, the component still fires them.
Bubbling confuses the issue; because if a component's child fires an event where the bubble property is true; then it is almost the same as that component firing the event. How, programmatically, would you figure that out without some sort of code analyzer?
That said, there is a compiler argument to retain metadata ( keep-as3-metadata at http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_14.html and http://jacwright.com/blog/72/using-your-own-custom-metadata-in-as3/ ).
I believe if you do that, then there is a way to get the event metadata from the component; I thought using describeType. But, remember that metadata is not the whole story in terms of events.

Data binding support in O/RM tools, how to detect

I want to verify that a generated class (single entity or collection) from an O/RM tool is data binding compatible.
I read that supported data binding types in WCF are: one time, one way, two way, one way from source in WCF. But how about "old school" .NET 1.1 data binding ?
It looks kind of difficult to check in code what kind of data binding support there is. You also have difference in runtime and design time data binding support. When reading some webpages I read different kind of implementations: implement IList, IComponent, INotifyPropertyChanged, IBindingList.... pffffff I don't know exactly where to look for...
You can databind to virtually any class. Let's imagine you create a very simple class, with a few properties, say for instance, Person with a Name and Age. I am talking about a plain simple class with absolutely nothing fancy about it.
If you create an instance of Person, you can do several things with it, and I will assume you are working with Windows Forms, but this mostly applies to other frameworks:
- You can bind its properties to properties of controls.
- You can bind it to datagrids, lists, etc. In the former case you can set mappings of which properties bind to which columns. In the latter, which property is displayed in the list, which property is the value selected by the user.
- Even better, you can bind it to a bindingSource.
Binding a single instance to a grid or a list isn't that useful, so what usually is done is that you create a list of instances and bind those to the grid. Even more correct is to bind the list to a bindingsource and the grid to the bindingsource also.
You can see a good article here about how to do all this.
Now, about all the interfaces you mention, they all only add more value to the databinding experience. Let's talk about a few of them.
INotifyPropertyChanged. Person is not less "databindable" than any other object if it does not implement this interface. What instances of Person are not able to do, however, is notify the controls their properties are bound to that the latter have changed. Try this: Bind the Name property of a Person instance to the Text property of a TextBox. Create a button that when clicked changes the value of that instance's Name. You will see the TextBox does not update after clicking the button. If, on the other hand, you implement INotifyPropertyChanged and have the setter of the Name property raise the PropertyChangedEvent that is defined by the interface, after repeating the experience, you will see that the textbox is updated automatically.
IEnumerable. If instead of a single Person, you want to databind not to a set of people, you can create a list of people and databind to that list. Let's take for instance, List lst = new List(); How do the databinding controls like datagrid, bindingSource, etc., know you want to bind to a set of Person(s) and not to the properties of lst itself? It is because List implements IEnumerable. So, whenever you bind these controls to an instance of anything that implements IEnumerable, the controls know that you intend to bind not to the properties of the list, but to the instances the list refers to. How do they know the type of objects the list contains? To be more generic and support any type of IEnumerable implementation, they just check the type of the first element in the list and assume all others are equal.
IBindingList: Even if Person implements IPropertyChanged, if you group instances of Person into a List bind that list to a control and, by code, change the value of a property of one of the instances, you will see nothing happen in the screen. This happens because Person is notifying, not the binding source, but the list. But the list wasn't made for databinding, so it is not listening, nor propagating the event to the control. Lists that implement IBindingList, like BindingList, offer a better databinding support precisely by listening to the PropertyChangedEvent events of their contents and propagating them up to the databound control.
I am affraid I have given you no way of determining if an object is databoundable, because virtually all them are, but I hope I've given you a way of determining different levels of databinding support (INotifyPropertyChanged and IBindingList). I am assuming you know how to check for these via reflection.
Any instance of a class with properties is data bindable. (in fact instances of any class with fields or properties at all are data bindable)
Using reflection in .NET makes it very easy to discover/use data in an object. (at a small performance cost)
In order to answer this question you'd need to provide the specific usage scenarios you'll be encountering.
Rui gives some good explanation of different common data binding patterns, but each of them is for solving specific problems.
The right answer is always dependent on the context.
:)

Resources