Passing array of QML elements to Javascript function
-
This is my first time using a declarative language and I have run into a few issues.
This application is meant to help count currency by number of units input by the user and displays the total face value to the user.
My first problem is I'm sending 9 elements to my FormCalculations.tillBalanceHandler individually
Is there a way to send something like... parent.children? and if so how do I reference them individually inside the javascript function?
//this is my main qml file Page1Form { //Handle calculations of tillBalanceNum tillBalanceNum.text: FormCalculations.tillBalanceHandler(quarterRollCalc, dimeRollCalc, nickelRollCalc, pennyRollCalc, tillQuarterCalc, tillNickelsCalc, tillDimesCalc, tillPennyCalc, extraChangeCalc) } //this is a small clip of how my elements in ui.qml look Column { id: column x: 5 width: 80 height: 316 spacing: 13 Text { id: quarterRolls width: 80 height: 20 text: qsTr("quarter rolls") font.family: "Verdana" font.pixelSize: 12 } Text { id: dimeRolls width: 80 height: 20 text: qsTr("dime rolls") font.family: "Verdana" font.pixelSize: 12 } Column { id: column1 x: 129 y: 0 width: 42 height: 316 spacing: 13 TextInput { id: quarterRollCount width: 30 height: 20 text: qsTr("#") validator: IntValidator{bottom:1; top:1000} font.pixelSize: 12 property double value: 10.00 } TextInput { id: dimeRollCount width: 30 height: 20 text: qsTr("#") validator: IntValidator{bottom:1; top:1000} font.pixelSize: 12 property double value: 5.00 } Column { id: column2 x: 217 y: 0 width: 42 height: 316 spacing: 13 Text { id: quarterRollCalc width: 80 height: 20 font.pixelSize: 12 } Text { id: dimeRollCalc width: 80 height: 20 font.pixelSize: 12 } //this is my javascript file function tillBalanceHandler(QRC, DRC, NRC, PRC, TQC, TDC, TNC, TPC, ECC) { var calcArray = [QRC.text, DRC.text, NRC.text, PRC.text, TQC.text, TDC.text, TNC.text, TPC.text, ECC.text] var iterator var totalToSubtract = 225 for (iterator in calcArray) { totalToSubtract = totalToSubtract - calcArray[iterator] } //result needs 2 digits after decimal var result = totalToSubtract.toFixed(2) return result }
my 2nd problem if possible is if someone could tell me if it's possible to batch together SignalHandlers?
//main.qml again Page1Form { //Handle Edits to Counts to Display Totals quarterRollCount.onEditingFinished: {quarterRollCalc.text = FormCalculations.countHandler(quarterRollCount)} dimeRollCount.onEditingFinished: {dimeRollCalc.text = FormCalculations.countHandler(dimeRollCount)} nickelRollCount.onEditingFinished: {nickelRollCalc.text = FormCalculations.countHandler(nickelRollCount)} pennyRollCount.onEditingFinished: {pennyRollCalc.text = FormCalculations.countHandler(pennyRollCount)} tillQuarterCount.onEditingFinished: {tillQuarterCalc.text = FormCalculations.countHandler(tillQuarterCount)} tillNickelCount.onEditingFinished: {tillNickelsCalc.text = FormCalculations.countHandler(tillNickelCount)} tillDimeCount.onEditingFinished: {tillDimesCalc.text = FormCalculations.countHandler(tillDimeCount)} tillPenniesCount.onEditingFinished: {tillPennyCalc.text = FormCalculations.countHandler(tillPenniesCount)} extraChangeCount.onEditingFinished: {extraChangeCalc.text = FormCalculations.countHandler(extraChangeCount)} } //javascript file function countHandler(countElement) { var countInt = parseInt(countElement.text) var value = countElement.value var total = (countInt * value).toFixed(2) return total }
If anyone has suggestions for how to approach QML/Javascript in this context, please do so I can make my life easier
thanks! -
@Gizmo
You should really have a look at:
http://doc-snapshots.qt.io/qt5-5.11/qtquick-modelviewsdata-modelview.html
It will solve both your problems...To get you going, try the following:
ListModel { id: myModel ListElement {denomination: "quarter rolls"; unitValue: 10.0} ListElement {denomination: "dime rolls"; unitValue: 5.0} ListElement {denomination: "nickel rolls"; unitValue: 2.0} ListElement {denomination: "penny rolls"; unitValue: 0.50} ListElement {denomination: "till quarters"; unitValue: 0.25} ListElement {denomination: "till dimes"; unitValue: 0.10} ListElement {denomination: "till nickels"; unitValue: 0.05} ListElement {denomination: "till pennies"; unitValue: 0.01} } Column { height: 20*myModel.count width: 80 padding: 10 Repeater { id: test model: myModel delegate: Row { height: 30 width: 100 Text { id: denomLabel width: 100 height: 30 font.pixelSize: 12 text: denomination } TextInput { id: countVal width: 100 height: 30 text: "1" validator: IntValidator{bottom:1; top:1000} font.pixelSize: 12 onAccepted: { totVal.text = (unitValue * parseInt(countVal.text)).toFixed(2) } } Text { id: totVal width: 80 height: 30 font.pixelSize: 12 text: unitValue.toFixed(2) //(unitValue * parseInt(countVal.text)).toFixed(2) } } } }
You can access model items via the get(index) method and items from the
Repeater
via the itemAt(index) method to access the values in the delegate that are not part of the model.Good luck!
-
I'm currently working with "totVal" and I need to access it within your solution.
How do I access the index of TotVal with itemAt()?
At this point I'm curious to reassign the index each time totVal is created within the repeater.I had totVal tell me the index of itself, but it seems the row is creating a problem?
I tried to assume perhaps it could be an array, (RowNum, ElementNum) but that didn't work either.
I tried test.itemAt(0).totVal and that didn't work either.
I'm able to see that test.itemAt(up to myModel.count).width only gives me the width of what the row is. -
@Gizmo
You are right in that it has to do with theRow
. You cannot directly accesstotVal
since it is not the root of the delegate. In your case the root is theRow
indeed. To access children of the delegate's root object, or their properties, you have to use analias
, for example like this:Repeater { id: test ... delegate: Row { ... property alias sumVal: totVal.text ... Text { id: totVal text: ... } } }
Now, you can access
sumVal
as:test.itemAt(index).sumVal
Note that aliases can also be to the object itself, so you could instead have done:
property alias totVal: totVal
and then use:
test.itemAt(index).totVal.text
to get the
text
value. -
Hahaha that's fantastic, I tried the property alias within the totVal {block} and it didn't work with all of this code inside my ui.qml. I finally realized that placing all of this in my main qml file makes life much easier and I have more freedom. Thanks again Diracsbracket.