Looping over the records of a large cfgrid
20 comments Posted by: LauraI mentioned in the post Adding the values of a cfgrid column that if we need to loop over many rows in the cfgrid, we may receive the "A script in this movie is causing Flash Player to run slowly" alert from the Flash Player. In order to avoid that, we’ll separate the task in frames:
<cfsavecontent variable="changePrice">
var newPrice = Number(amount.text);
var i = 0;
//make the loop with onEnterFrame instead of a "for"
_root.onEnterFrame = function ()
{
if(i < productsGrid.length) {
//do one iteration of the loop
_root.updatePrice(i);
i++;
}
else {
//end the loop
_root.onEnterFrame = undefined;
}
}
//this is the function that does whatever we need in each iteration
_root.updatePrice = function (index){
//edit the row
productsGrid.editField(index, 'price', Number(productsGrid.getItemAt(index)['price']) + newPrice);
//change the color of the edited row
productsGrid.setPropertiesAt(index, {backgroundColor:0xF7FFB7});
}
</cfsavecontent>
<cfform name="myForm" format="flash">
<cfgrid name= "productsGrid" query="products">
<cfgridcolumn name="name" header="Product">
<cfgridcolumn name="price" header="Price" type="numeric">
</cfgrid>
<cfinput type="text" name="amount">
<cfinput type="button" name="updateBtn" value="Update" onclick="#changePrice#">
</cfform>
Live example
Download the source
20 Comments so far
Write yoursFirst loop over the data, edit it, then
set grid.dataprovider at once.
This is more efficient than editing
1 row at a time.
<cfsavecontent variable="uncheck">
_root.onEnterFrame = function() {
if (i < _root.myGrid.length) {
_root.myGrid.editField(i, 'send', false);
i++;
} else {
_root.onEnterFrame = undefined;
}
};
</cfsavecontent>
<cfform format="flash" name="flashForm" width="540" height="580" skin="halosilver">
<cfgrid name="myGrid" Format="flash" query="q_mailingList" selectmode="edit" delete="yes" insert="yes" fontsize="10" rowheight="25" gridlines="yes" colheaders="yes" height="500">
<cfgridcolumn header="id" name="listID" display="no">
<cfgridcolumn header="LAST NAME" name="lastName">
<cfgridcolumn header="FIRST NAME" name="firstName">
<cfgridcolumn header="EMAIL" name="email" width="185">
<cfgridcolumn header="DATE ADDED" name="date" width="80" select ="no">
<cfgridcolumn header="SEND EMAIL" name="send" width="80" type="boolean">
</cfgrid>
<cfformgroup type="horizontal">
<cfinput type="button" name="uncheckAll" value="UNCHECK ALL" onclick="#uncheck#">
</cfformgroup>
<cfformgroup type="horizontal">
<cfinput type="submit" name="gridEntered" value="SAVE">
</cfformgroup>
</cfform>
If you could help me out that would be greatly appreciated. Thanks!
Eric
yes, you can use dataprovider and it will definitely be faster. I wanted to give the user some kind of visual indication that the something was happening, so that is why I edit each row. In the other case, we could pop an alert when the process was finished.
You can also make a small loop (ie: 5 iterations) inside the onEnterFrame function to edit more than one row each time to make it faster.
Your code is working for me. I only needed to declare the variable i before using it. Also make sure that the column send in your db (or query) has the same case as in the AS code.
var i = 0;
_root.onEnterFrame = function() {
.......
}
Trying to get a simplified version of this to work...Any help will be appreciated!
<cfquery name="products" datasource="#application.dsn.oiws#">
SELECT *
FROM tbl_List360
ORDER BY lastName
</cfquery>
<cfoutput>
<body>
<cfform name="myForm" format="flash" width="350" height="250">
<cfformgroup type="vBox">
<cfgrid name= "cart" query="products" height="150" rowheaders="false" selectmode="edit">
<cfgridcolumn name="RACF" header="Product" select="true">
</cfgrid>
</cfformgroup>
</cfform>
</body>
</cfoutput>
Our back end is SQL Server, in this table are several records. I want to give the user the ability to edit specific fields in this dataset through the cfform. What I've ran into so far is that the dataset is not populating the form. It feels like I'm missing a cfloop, or something to populate the form (at this point the form returns blank).
Anybody come up with something?
If you could tell me what to look for in AS.
If you want to send the items of a grid you should send it like this:
myGrid.dataProvider.items
Mafdoc,
You can unselect the grid with this code:
myGrid.selectedIndex = undefined;
I added this
myGrid.selectedIndex = undefined;
and
myfieldnames.text ="";
and when the button is clicked
all the fields and the grid are cleared.
Thanks again.
My situation is this: I have two cfgrids, both are populated via a query. You can click on a row in the first grid and add it to the second grid. Then I want to be able to save the data the is added to the second grid into the database. Is this possible? I'm sure it's similar to what you guys have written here, but I'm not sure exactly how to use it.
Here is my code of my two grids:
<cfformgroup type="horizontal">
<!---<cfformitem type="text">Existing Users</cfformitem>--->
<!--- Testing how a CFGRID will work ---> <!--- Testing how a CFGRID will work --->
<cfgrid name="user_grid" query="getEmployees" selectmode="row" colheaders="yes"
rowheaders="no" width="250" height="200" format="Flash" onChange="#gridChange#">
<cfgridcolumn name="EmpID" header="Employee ID" display="no">
<cfgridcolumn name="Last_Name" header="Last Name">
<cfgridcolumn name="First_Name" header="First Name">
<cfgridcolumn name="Phone_Number" header="Phone Number" display="no">
<!---<cfgridcolumn name="UserLevel" header="User Level" display="no">--->
<!---<cfgridcolumn name="OffAbbr" header="Office" display="no">--->
</cfgrid>
<!---<cfformitem type="text">Users Assigned to the Project</cfformitem>--->
<!--- Testing 2nd CFGRID --->
<cfgrid name="user2_grid" query="choosenUsers" rowheaders="no" width="400" height="200" format="flash">
<cfgridcolumn name="EmpID" header="Employee ID" display="no">
<cfgridcolumn name="Last_Name" header="Last Name">
<cfgridcolumn name="First_Name" header="First Name">
<cfgridcolumn name="Phone_Number" header="Phone Number" mask="(999)999-9999" display="no">
<cfgridcolumn name="UserLevel" header="User Level">
<cfgridcolumn name="OffAbbr" header="Office">
</cfgrid>
</cfformgroup><!--- End Two Grids --->
Any help is appreciated.
Thanks!!
Thanks in advance
Case
My 5 cents :
You can add a "kind of" counter in your form, something like :
<cfinput type="Text"
name="counter"
required="No"
visible="No"
enabled="No"
size="15"
style="text-align:center;borderStyle:none;disabledColor:#000000;background-color:transparent;">
and then, in your cfsavecontent :
var newPrice = Number(amount.text);
var i = 0;
_root.onEnterFrame = function ()
{
_root.counter.visible = true;if(i < productsGrid.length) {
_root.counter.text = "Processing " + i + " rows ...";_root.updatePrice(i);
i++;
}
else {
_root.counter.visible = false;_root.onEnterFrame = undefined;
}
}
Hope this helps !
Here is the function call to loop through the datagrid rows:
<cfsavecontent variable="calculateTotal">
var totalAmount = 0;
var item;
var subTotal = 0;
var itemStr:String = "foo";
for(var i = 0; i < cart.length; i++) {
item = cart.getItemAt(i);
//get subtotal
subTotal = number(item['price']) * item['quantity'];
itemStr = itemStr + ':' + item['name'].toString();
//tally up the amount
totalAmount += subTotal;
//change the subtotal column for this row
cart.editField(i, 'amount', subTotal);
}
//show the total
total.text = totalAmount;
names.text = itemStr;
</cfsavecontent>
Here is the function call to loop through the datagrid rows:
<cfsavecontent variable="calculateTotal">
var totalAmount = 0;
var item;
var subTotal = 0;
var itemStr:String = "foo";
for(var i = 0; i < cart.length; i++) {
item = cart.getItemAt(i);
//get subtotal
subTotal = number(item['price']) * item['quantity'];
itemStr = itemStr + ':' + item['name'].toString();
//tally up the amount
totalAmount += subTotal;
//change the subtotal column for this row
cart.editField(i, 'amount', subTotal);
}
//show the total
total.text = totalAmount;
names.text = itemStr;
</cfsavecontent>