Passing parameter in flex function - apache-flex

I have several TextInputs in a certain form which have been assigned id in an incremental order. For example:
<s:TextInput id = "index1"/>
<s:TextInput id = "index2"/>
<s:TextInput id = "index3"/>
Based on certain conditions I select the text from the corresponding TextInput and pass the value (index#.text) into a function
foo(var index:String)
If I had just one of the TextInput I could have used:
foo(index1.text)
Can someone suggest how I can pass the textInput using its id.
Thank you.
-H

I plus one the request for 'certain conditions'. You post alludes to the fact that you can't access the component by name, so I'm writing the rest of this based on that assumption.
To access the values of a component and pass parameters of that component into a function you need an identifier, or link, to that component. It is easiest if you use the components name. But, that is not always possible. For example, the Flextras Calendar component creates, and displays, the days of the month. Depending what month is displayed, there may be 28, 30, or 31 days. It is not practical to access them by a unique name.
this is a similar situation in a ListBased class. You won't know, at compile time, how many itemRenderers you're going to need or have on the screen at one time.
One way to approach this is to have an array of the relevant objects (dayRenderers, itemRenderers, or in your case TextInputs). When doing processing you can loop over the array and process the element. Something like this:
for (var x = 0; x<objectArray.length; x++){
foo(objectArray[x].text);
}
If that is not desirable to you, for whatever reason, you can loop over the children of a container doing something like this:
for (var x = 0; x<container.numChildren; x++){
var object : Object = this.getChildat(x);
if(object is TextInput){ foo(object.text) }
}
Functional, but it can be a bit tedious at times. It really depends what you're trying accomplish.

Related

In Golang, can I customise key comparison, if I am taking struct as key?

How does map in Golang compare keys? For some reason, I need to have a struct as a key, which has 2 values inside. I want map to compare by only first value, not second. Second is for my usage. Like in java, I can customise equals method, so map will take only logically equal keys within. Is there any way to do that?
Edit: Looks like there is no way to do that. So I am now putting down my problem here. Please help me to think in 'Go-way'.
So, I want to implement a 'timed map', which tracks the key insertion time. In other words, there is a map which accepts and processes the values. Now, if the data in map is older than some specific time-interval, then I should clear it out.
So, I thought of having a key struct which has id and timestamp. When a new key comes, map takes it with id and currentTimeInMillis. After sometime, if a key comes which already exists, then map should preserve the first insertion time and only updates the value array.
To process, I will have a looping over map and check if any particular key is inside for more than threshold limit, then I clear it out. I can have this timestamp in value array, but that also has a timestamp of its own, so putting one more might confuse someone else.
Please suggest something.
Put the time on your value. Here's some example of how to structure your data.
type DataObj struct {
Id int
Updated time.Date
// other fields
}
m := map[int]DataObj{}
m[d.Id] = d // assign using the id as your key
for k, v := range m {
if time.Since(v.Updated) > duration {
delete(m, k) // remove the stale item
}
}
// some logic like this for adding/overwriting
v, ok := m[newObj.Id]
if ok { // an element with this id existed
if time.Since(v.Updated) > duration {
m[v.Id] = newObj // assign new value over old one
}
}
I can't provide anything much more specific because you don't have any code with which to work. It seems like you'd probably like some of this (like the remove bits) to run on a timer. To do that, invoke the function as a goroutine and use a timer so every X seconds it unblocks and removes items from the map. If you're doing this you also need to use a mutex so the calling scope doesn't access the map while the remove function running the background is filtering out old items.
The overwrite bit is really straight forward, just test if the item is in the map, check it's time stamp, if it's beyond the threshold assign the new value, if not do nothing.
The main thing to take away here is to not use a struct for your key... There is no reason to do object equality, your object has an id, us it as your key. Everything else you care about can be held on the value (even the key itself is). As someone pointed out this isn't Java and even if it were, equality overrides in C# and Java are literally a fucking nightmare.

Databinding with a large amount of values and getter methods?

Reading through Misko's excellent answer on databinding here: How does data binding work in AngularJS?, I am wondering how Angular does it's dirt-checking behind the scenes, because:
I'm creating an app, that prints a large amount of Car objects to the DOM, each Car looking something like this:
var Car = function(settings) {
this.name = settings.name;
+ many more properties...
}
Car.prototype = {
calcPrice: function() { ... },
+ many more methods...
}
$scope.cars = [lots of Cars];
The linked answer above mentions a limit of around 2000 values that can be provided through databinding when printed in the DOM, and due to the large amount of properties on each Car object, this number could very easily be exceeded in this app when looping through the cars array.
Say you end up having 2000+ values printed in the DOM through databinding, and one of these values updates, does it affect Angular's dirt-checking performance that 2000 values are present, or does Angular somehow flag the values that change, so it only looks at the changed values when running its $digest()? In other words, does it matter that you have a lot of databound values, when only a very small number of these are likely to be updated after the initial print?
If it does matter, -- and since most of the values are read-only -- is there some way to use the databinding syntax {{car.prop}} to get the value to the DOM once and then tell Angular to not bind to them anymore
Would it make a difference to add getter-methods to the Car object and provide it's properties like this {{car.getProp()}} ?
I had the same kind of problem with an application I was working on. Having a huge data set is not a problem, the problem comes from the bindings,ng-repeats in particular killed performances.
Part of the solution was removing "dynamic" bindings with "static" bindings using this nice library: http://ngmodules.org/modules/abourget-angular.

list.dataGroup.getElementAt() not returning all the elements

I'm trying to cycle through my list itemRenderers to change the data of a particular item. The code runs well until the for index becomes 7 (which is the maximum number of visible elements on my list). When the index is 7 or more, the getElementAt() function returns null. What could possibly be the problem?
var itemRenderer:ItemRenderer;
var numItems:int = list.dataGroup.numElements;
trace(numElements) // outputs 14
for(var i:int = 0; i < numItems; i++){
itemRenderer = list.dataGroup.getElementAt(i) as ItemRenderer;
if (itemRenderer.data.name == "bar") {
itemRenderer.data.option = "foo";
break;
}
}
If you want to change the data of a particular item, why not change it from the data you gave to the dataProvider? Changing it directly in the item renderer is ludicrous.
And for future reference, the reason why that fails is because of something called virtualization. Essentially, not all item renderers are created, only the ones visible.
Spark List uses virtual layout by default (useVirtualLayout = true). It allows to reuse item renderers and increase performance and decrease resources usage. In your case you can set useVirtualLayout=false for your List.
But it is very possible you do something wrong if you need to list List's item renderers from outside. Try to solve your problem some other way and remain using virtual layout.
You can also use the RendererExistenceEvent which is fired when the ItemRenderer of the DataGroup when it receives data and is rendered. Listen for the event rendererAdd on the DataGroup.
<s:DataGroup id="dataGroupList" dataProvider="{_listData}"
width="100%" height="100%"
rendererAdd="list_rendererAddHandler(event)"/>
For more information, check out the help document for RendererExistenceEvent.
Though some say it's not best practices for accessing and changing data in the ItemRenderer directly, there may be other use cases where you need to just that. For instance, if you want to toggle the selected or enabled properties of the list based on some user interaction or state change. Best practices only apply on the simplest use cases, other use cases require you to use these events or modify the control itself.

How to programatically control an object's add-menu list of allowed content types?

I would like pragmatically to control individual objects' add-menu list of allowed content types.
I am building a collection of content types with archgenxml. In one case, I have a simulation class composed of a RangeBase class which has three realizations, valueRange, vectorRange and uniformRange. A simulation can contain exactly one range, i.e., RangeBase's multiplicity is one, so a simulation's add-menu should offer either all three range types or none at all.
To achieve this, I thought to subscribed to the IObjectInitializedEvent and IObjectRemovedEvent events; placing their respective handlers, initializedHook and removedHook, in the RangeBase class. The handlers would solicit an object's list of locally allowed types and remove or add the three ranges accordingly. After perusing the Plone's 'Community Developer Documentation', I thought the initializedHook code might look something like this:
# Set allowed content types
from Products.ATContentTypes.lib import constraintypes
def initializedHook(obj, event):
# Get this range's parent simulation
parent = obj.aq_parent
# Enable constraining
parent.setConstrainTypesMode(constraintypes.ENABLED)
# Remove the three ranges
allowedTypes = parent.getLocallyAllowedTypes()
ranges = ('valueRange','vectorRange','uniformRange')
for range in ranges:
allowedTypes.remove(range)
# Tweak the menu
parent.setLocallyAllowedTypes(allowedTypes)
parent.setImmediatelyAddableTypes(allowedTypes)
Unfortunately, my simulation class has none of these functions.
Is there an adaptor that will provide my simulation class with this functionality, or are there other altogether different approaches to achieve the desired menu behaviour? Any suggestions would be appreciated.
It is possible.
I believe you need to override getLocallyAllowedType()
http://svn.plone.org/svn/collective/Products.ATContentTypes/trunk/Products/ATContentTypes/lib/constraintypes.py
AT was written time before adapters, so AT is not using it.
I suggest you could also update the documentation regarding this... it is pretty common use case.
http://web.archive.org/web/20101010142032/http://collective-docs.plone.org/content/creating.html
After several unsuccessful attempts at tweaking _allowedTypes(), I followed the last suggestion at http://plone.org/documentation/kb/restrict-addable-types and customized getNotAddableTypes.py. My customization merely lists a folder's contents filtering for the three ranges. If the resulting array is not empty, I add the three range types to the list:
# customize this script to filter addable portal types based on
# context, the current user or other criteria
ranges = []
ranges = context.listFolderContents(contentFilter={'portal_type':
('VectorRange','ValueRange','UniformRange')})
return {True: ('Favorite', 'VectorRange', 'ValueRange', 'UniformRange'),
False: ('Favorite')}[len(ranges)]
See the last post here for two possibilities: http://plone.293351.n2.nabble.com/Folder-constraints-not-applicable-to-custom-content-types-td6073100.html
The method
foo.getLocallyAllowedTypes()
gives back a tuple, that you just have to copy / filter into another tuple / list, because it's immutable.
allowed_types = parent.getLocallyAllowedTypes()
filtered_types = []
for v in allowed_types:
if not v in ranges:
filtered_types.append(v)
Then you can just give that tuple to the setter method
parent.setLocallyAllowedTypes(filtered_types)
and your're done. But if you want to access the parent during object creation to restrict content types of the folder, you creating the object in, you can hook up in at_post_create_script() and manage_beforeDelete() from BaseObject. This works great for me, restricting the number of specific content types to a folder and also corrects the AllowedTypes when the object gets deleted.

Flex: select tree node right after the dataProvider is been assigned / updated / replace

i have a Flex tree control and im trying to select a tree node 3 levels down right after the dataProvider is assigned with a collection object like the following.
basically treeItem1, treeItem2, treeItem3 are the nodes in the tree and treeitem3 is a child of treeItem2 which is a child of treeItem1. Assume these treeItem(1,2,3) are referenced correctly from the collection items.
my problem is that if i wait for the whole component to load completely then select the nodes, it open/select/scrolltoIndex correctly. However, if i were to select the node right after the dataProvider is assigned, then it doesn't even open or select (basically the this.treeService.selectedItem is always null).
can anyone point out what i did wrong? is there anything needs to happen after the dataProvider is assigned?
thanks
this.treeService.dataProvider = oPricingHelper.getCurrentPricingSercicesTreeSource();
this.treeService.expandItem(treeItem1, true);
this.treeService.expandItem(treeItem2, true);
this.treeService.selectedItem = treeItem3;
this.treeService.scrollToIndex(this.treeService.selectedIndex);
I have used the updateComplete event to know when a component (such as a DataGroup or List) has completed rendering after performing a simple task (such as updating the dataProvider reference). Of course, you have to be careful and remove listening to updateComplete because it can run a lot, unless you have a need for it to run.
Something like:
//...some function...
this.treeService.addEventListener(FlexEvent.UPDATE_COMPLETE, onTreeUpdateComplete);
this.treeService.dataProvider = oPricingHelper.getCurrentPricingSercicesTreeSource();
//...rest of some function...
private function onTreeUpdateComplete(event:FlexEvent):void {
this.treeService.removeEventListener(FlexEvent.UPDATE_COMPLETE, onTreeUpdateComplete);
this.treeService.expandItem(treeItem1, true);
this.treeService.expandItem(treeItem2, true);
this.treeService.selectedItem = treeItem3;
this.treeService.scrollToIndex(this.treeService.selectedIndex);
}
I'm not positive your experiencing the same issue but I seem to have the same type of problem with using the advanced data grid, it appears in these cases where the dataprovider is acceptable as multiple types, the components do some extra work in the background to wrap things up into something Hierarchical (HierarchicalData or HierarchicalCollectionView) and in doing so the dataprovider setter call is not synchronous (so it will return before actually having assigned the internal property storing the dataprovider). I've used callLater in this case with moderate success, callLater is generally a bad practice but basically adds a function to a list of functions to call once background processing is done, so this is assuming that something in the dataprovider setter called UIComponent.suspendBackgroundProcessing() and that it will subsequently call UIComponent.resumeBackgroundProcessing() and then it will execute the list of functions added by using callLater. Alternatively you could use setTimeout(someFunction,1000).
These are both "hacks" the real solution is to dig into the framework code and see what it's really doing when you tell it to set the dataprovider. Wherever you see that it actually has set the dataprovider you could extend that class and dispatch an event that you could listen for to run the function to do the selections after this point.
If anyone has a better solution please by all means correct me (I would love to have a better answer than this)

Resources