QML Access a Component using a string to reference it´s ID - qt

Here is the thing. I need to do the same processing for 16 Custom Input Boxes. This is a drag. So I thought I could add their ids to some sort of list and then iterate through a list, calling on a fucntion that does the processing.
Problem is I don't know how to access the component (to get the inputted text and set some variables inside it) when the id is in a string variable. Is this possible?

I'm leaving an answer here, in case it is of any help to anyone.
As it turns out you can just pass the input element as a parameter to a function. So lets say that you have
TextInput{
id: input1
...
}
TextInput{
id: input2
...
}
You could do this:
var list = [input1, input2]
for (var i = 0; i < list.length; i++) doStuffFunction(list[i])
And inside the function...
function doStuffFunction (imp){
var thetext = imp.text
//... Do more stuff
}

Related

How to use the widget fullpath to access widget's properties?

I know that using widget.getFullPath() method, we can retrieve the full path of a widget as a string in the format "pagename.child1name.child2name....childNname.widgetname".
I am trying to find a way for using this string to access the original widget.
I was successful using this:
app.pages["pagename"].children["child1name"].children["child2name"]....children["childNname"].children["widgetname"].text = "some text";
but I don't know how to change this in a more general function, independent by the depth of the path.
Any idea would be very much appreciated. Thank you.
The parent root descendents should have everything on the page, so try:
widget.parent.root.descendants.ANYTHING.value;
you might alternately need to do this if you want ANYTHING to be a variable
widget.parent.root.descendants[ANYTHING].value;
My intention is to access the widget's property from another page. The root of a widget is its page, and it is the string before the first dot in the full path.
I eventually wrote a function which builds the object after splitting the full path string in an array:
function getWidgetPath(pathString) {
var pathArray = pathString.split('.');
var widgetPath = app.pages[pathArray[0]];
for( i=1; i<pathArray.length; i++ ) {
widgetPath = widgetPath.children[pathArray[i]];
}
return widgetPath;
}
The function can be used to build the target object. I.e., considering that the target widget is a label and I want to change its text property, I use:
var targetPath = 'parentpage.panel1.panel2.panel3.label1';
var targetWidget = getWidgetPath(targetPath);
targetWidget.text = 'some text';
I have the feeling that it's not very Javascriptian, though.

How do I create the correct KeyboardEvent objects for a given string of text?

I'd like to simulate some keyboard input by dispatching KeyboardEvent objects manually. Creating such events involves passing a key code.
Alas, I only have a given string
const text: String = "Hello";
I can easily get the char code using String::charCodeAt, but how can I get the key code? For any given character (say: "H") there may be just a single key code, a key code plus some modifier (in this case: Shift + keycode_of_h) or even multiple key codes. Is there maybe a way to get the key code for a given char code (possibly by considering the keyboard mapping of the user)?
This isn't too difficult but it will just take a little bit to set up.
First create a dictionary or Object mapping the UTF-8 values to key values like this:
var keyCodes:Dictionary = new Dictionary();
keyCodes[49] = Keyboard.NUMBER_1; //1
// add the rest of the mappings...
Then because you need to specify SHIFT
var shiftedKeyCodes:Dictionary = new Dictionary();
shiftedKeyCodes[33] = Keyboard.NUMBER_1; //!
// add the rest of the shifted mappings
Then create a utility function like this:
public function charCodeToKeyboardEvent(charCode:int):KeyboardEvent{
var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP);
event.charCode = charCode;
if(keyCodes[charCode]){
event.keyCode = keyCodes[charCode];
} else if (shiftedKeyCodes[charCode]){
event.keyCode = shiftedKeyCodes[charCode];
event.shiftKey = true;
} else {
return null;
}
return event;
}
Then loop through your string and do this:
for(var i:int = 0; i < myString.length; i++){
dispatchEvent(charCodeToKeyboardEvent(myString.charCodeAt(i)));
}
EDIT: I updated this to use the constants on the Keyboard class so that it will work independent of device or operating system.
It turns out that I didn't need a 100% correct KeyboardEvent in the first place. Instead, there were two things I was missing:
A flash.events.TextEvent needs to be dispatched for plain text (like "Hello") input.
The events need to be dispatched to the embedded edit control which can be accessed using the textDisplay property.

Flex: Is it possible to pass multiple strings between views?

I have a list of text files and when one is selected it is read and assigned to a string variable. this string is then pushed to a view : pushView(viewer, string), where the string is displayed in a textarea. I want to also pass the relative path of the file also. Is this possible to pass two strings?
protected function view1_viewActivateHandler(event:ViewNavigatorEvent):void
{
if(data!=null){
mainTextField.text = data.toString();
}else{
mainTextField.text = "";
}
}
Yes it is possible. Typically the way I do this in Flex is to add a data property on my view of type Object allowing me to pass any type of object into the view.
In your case I would change pushView(viewer, string) to something like pushView(viewer, data) where data is some object that stores all the data you need to pass to the view. data might look like:
var data:Object = { text: "my text to display",
relativePath: "the/relative/path" };

CheckBox header renderer with HierarchicalCollectionView

I've gotten a checkbox header renderer to work well with flat DPs, but a
hierarchical collection view is another story. On click, I want it to select all
checkboxes in a given column. Here is my code:
var dp:HierarchicalCollectionView = _dataGrid.dataProvider as
HierarchicalCollectionView;
var testDp:GroupingCollection = dp.source as GroupingCollection;
var rawDp:ArrayCollection = testDp.source as ArrayCollection;
for(var i:int=0 ; i < rawDp.length ; i++){
rawDp[i][_dataField] = cb.selected;
}
It selects all checkboxes on the 2nd level of data, but doesn't select the top
level of data. What am I missing here? I can't seem to find it.
Any tips are greatly appreciated. Thank you.
For hierarchical data you have to use a cursor which iterates over all levels of the hierarchical data.
var dp:IHierarchicalCollectionView = _dataGrid.hierarchicalCollectionView;
var cursor:IViewCursor= dp.createCursor();
while (!cursor.afterLast)
{
cursor.current[_dataField] = cb.selected;
cursor.moveNext();
}
Howerver, this works only with nodes that have previously been opened. So either expand all nodes with _dataGrid.expandAll() (you can collapse them afterwards since the nodes only have to be opened once) or iterate your hierarchical data manually:
function setCheckBoxValue(children:ArrayCollection, value:Boolean):void
{
for each (var child:Object in children)
{
if (child.hasOwnProperty("children") && child["children"])
setCheckBoxValue(child["children"], value);
child[_dataField] = value;
}
}
var myDataProvider:HierarchicalData = /* your data provider */;
// Call it like this...
setCheckBoxValue(myDataProvider.source, cb.selected);
Update: To answer your second question...
Create a new CheckBoxColumn which extends AdvancedDataGridColumn. You can use it to preconfigure your headerRenderer and itemRenderer.
In your custom item renderer you get hold of your column like this:grid = AdvancedDataGrid(listData.owner);
column = grid.columns[listData.columnIndex] as CheckBoxColumn;
Do the same in your header renderer.
Whenever the CheckBox value in one of your item renderers changes dispatch a event through your column. Something like: column.dispatchEvent(new Event("checkBoxValueChanged"));
Your header render should add an event listener to the column for the "checkBoxValueChanged" event (or whatever you call it). Whenever that event is fired loop through your data provider and update the headers CheckBox accordingly.
In theory that should work. HTH

Ideas on making a javascript object name unique in ASP.Net?

I've created an ASP.Net user control that will get placed more than once inside of web page. In this control I've defined a javascript object such as:
function MyObject( options )
{
this.x = options.x;
}
MyObject.prototype.someFunction=function someFunctionF()
{
return this.x + 1;
}
In the code behind I've created MyObject in a startup script --
var opts = { x: 99 };
var myObject = new MyObject( opts );
When a certain button in the control is pressed it will call myObject.someFunction(). Now lets say the value of x will be 99 for one control but 98 for another control. The problem here is that the var myObject will be repeated and only the last instance will matter. Surely there's a way to make the var myObject unique using some concept I've haven't run across yet. Ideas?
Thanks,
Craig
Your Javascript like this:-
function MyObject(options) { this.x = options.x; }
MyObject.prototype.someFunction = function() { return this.x + 1; }
MyObject.create(id, options) {
if (!this._instances) this._instances = {};
return this._instances[id] = new MyObject(options);
}
MyObject.getInstance(id) { return this._instances[id]; }
Your startup javascript like this:-
MyObject.create(ClientID, {x: 99});
Other code that needs to use an instance (say in the client-side onclick event)
String.Format("onclick=\"MyObject.getInstance('{0}').someFunction()\", ClientID);
Note the low impact on the clients global namespace, only the MyObject identifier is added to the global namespace, regardless of how many instances of your control are added to the page.
If it is just one value, why not have the function take it as a parameter and build your onclick handler so that it puts the correct value in for each control. If it is more complex than that, then consider making options an array and, for each control, insert the correct options into the spot in the array that corresponds to each particular control. Then pass the proper index into the array into the function.
I do this by using ScriptManager.RegisterClientScriptBlock to register a string as a JavaScript block on the client side. I can then modify my script string using {0}, {1}..,{n} place holders to inject necessary ids. It depends on the structure of your code as to if this is the most elegant fashion, but it works in a pinch. You could then inject variable names using references to Me.ClientID.
You can make the value of "x" static and access it anywhere in the code, such as:
function MyObject( options ) { MyObject.x = options.x; }
MyObject.x = 99; // static
MyObject.prototype.someFunction = function () { return MyObject.x + 1; }
This way you can access MyObject.x anywhere in your code, even without re-instanciating MyObject.
Excellent solution Anthony. The other solutions offered were as good and I did consider them but I was looking for something a little more elegant like this solution.
Thanks!

Resources