Archive for August, 2009
Seemingly Bizarre Type-Coercion Error
What The Flex?!
About an hour ago I started work on a new class and ended up with quite a strange error message which looked a little like this (the names have been changed to protect the innocent)
TypeError: Type Coercion failed: cannot convert Project.folder::MyClass@2d28301 to Project.folder.MyClass
Spot the oddity?
Cannot convert Project.folder.MyClass@2d28301 to Project.folder.MyClass. Hmmmm.
This one had me a little stumped.
The project I'm working on at the moment is modular and the only difference I could see was that this object was both created and added to a global collection from within a particular module, then I was attempting to retrieve it from the next module, whereas all the other data objects were instantiated in the application start up process, then retrieved from within various modules.
Solution
A quick post on FlexCoders got me the answer I was looking for. My object belonged to a different Application Domain than the rest, and therefore as far as Flex knew, these two classes were different.
The fix was to specify the ApplicationDomain for my module loader:
-
_mainModuleLoader = new NoviaModuleLoader(); //extends ModuleLoader
-
_mainModuleLoader.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
Thanks very much to Ian Thomas on FlexCoders for providing the solution.
You may also be interested in reading this.
10 commentsFiltering an ArrayCollection On Multiple Properties/Values
In my application I have an ArrayCollection containing some objects. I only want to display certain subsets of these objects in certain view components, and I can achieve that by applying a filter function to the collection, but sometimes you may wish to filter on multiple properties or property values. First, let's take a quick look at how the filter function works:
Basic Filtering
Each time the filter function gets called it receives an Object (an item from your ArrayCollection) and must return true or false - false if you want the object to be filtered out of the collection.
Let's suppose we have a collection of objects with a name property, and each object looks a bit like this: {name:"someNameString"}. We may want to only show objects with the name "AAA". Therefore our filter function may look like this:
-
collection.filterFunction = myFilterFunction; //set the function to use
-
collection.refresh();//must do this to cause anything using the collection to update.
-
-
private function myFilterFunction (item:Object):Boolean
-
{
-
return ( item['name'] == "AAA" );//returns true only if our ArrayCollection item 'name' property is "AAA"
-
}
Filtering On More Than One Value
Now what if you want to filter on multiple properties or multiple property values? Say we wish to filter properties that have either the name value "AAA" or the name value "EEE"? We could create a filter function like this:
-
private function myFilterFunction1 (item:Object):Boolean
-
{
-
return ( item['name'] == "AAA" || item['name'] == "EEE");
-
}
... but what if we now wish to filter objects with the names "AAA" or "BBB"? Well we could create yet another function to do that, and what if we want to filter on values "BBB" and "CCC" ..... as you can probably tell, if we have multiple values and wish to filter on any combination of these values it's going to lead to a combinatorial explosion of filter functions very quickly.
It would be better if we could send these values in as arguments to our filter function and have our function check against all of them, but sending in arguments doesn't seem to be an option, so instead we can set a class level property on our main class which can hold all the values we wish to filter on.
Creating A Basic Filtering Class
Rather than do that, it's best to encapsulate this functionality in to a separate class with the specific responsibility of taking care of our filtering. We can create a class with a property that can hold an array of filter values, and a function on that class which will generate our filter function for us too.
If that was as clear as mud, let's say our new class is called FilterSelector and see how we would use it in our application:
-
//IN OUR MAIN CLASS...
-
var fs:FilterSelector = new FilterSelector();
-
fs.filterField = "name"; //filterField is a property we've created to hold the field we want to filter on
-
fs.addFilterTypes("AAA", "CCC", "EEE");//the values we want to filter on.
-
-
collection.filterFunction = fs.generateFilterFunction();//USE THE OBJECT TO GENERATE THE FILTER FUNCTION
-
collection.refresh();
Inside the FilterSelector class, our generateFilterFunction() may look like this:
-
public function generateFilterFunction():Function
-
{
-
var f:Function = function(item:Object):Boolean
-
{
-
for each(var type:String in _filterTypes)
-
{
-
if(item[filterField] == type) return true;
-
}
-
return false;
-
};
-
return f;
-
}
As you can see, the generateFilterFunction() function returns an object of type Function. What it actually does is to create an anonymous function (a function without a name), which will loop over all our filter types, and returns this anonymous function to us, which we then set as the filter function. This anonymous function will return true as soon as any match is found, else return false if there are no matches.
Extending The Class
There are lots of places you can go with this. It may also be the case that you want to filter on different properties (ie rather than "AAA", "BBB", you may wish to filter on "name", "label") in which case you could accept multiple values for the filterField property too, then set up a nested loop for both property & value, and cross check each one.
In reality you may actually need multiple filter functions, as they may be markedly different. You could create another class with a specific type (eg IFilterFunction) and set the function you wish to use as a property on the FilterSelector class - this could get tricky, depending on how complex and specific your filters are, or you could do something similar to what is described in these posts: here & here.
Apologies for this rushed post (and hence lack of embedded working Flex example). Here is a link to a working example, exported as a Flex Project Archive .
I've not looked at the filtering in Flex ArrayCollections before. If you think you have a better solution feel free to chime in :]
1 commentAdding a Namespace-Qualified Attribute Using e4x
Just wanted to write a quick post, mainly to serve as a reminder for myself :]
I was asked to generate some XML (in Flex) which returned
<nodeName xsi:nil="true"/>
for any nodes that didn't have a value assigned to them (actually in our case we wanted this where the value was 0). Apparently, in .NET if the node value expected back is of type Integer .NET won't accept (or has trouble accepting)
<nodeName/>
I was a little unsure of how to generate an attribute with a namespace prefix using code. All credit goes to Graeme for coming up with the solution before me. Thought I'd post it here along with this great resource link.
Here's how it was generated:
-
var n:Namespace = new Namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
-
xml.addNamespace(n); //where 'xml' is the variable your XML block is assigned to
-
if( initialMin == 0){
-
xml.initialMinimum.@n::nil = "true";
-
}else{
-
xml.initialMinimum = initialMin;
-
}
If initalMin is 0 it will generate this XML:
-
<myXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
<initialMinimum xsi:nil="true"/>
-
</myXML>