I'm using CFGRID and CFGRIDUPDATE to insert values into a database. The problem is, each record needs to get an additional field that isn't in the grid. Is there any way to save that additional field to the record, or do I have to whip up an alternative to CFGRID?
Basically, I have a bunch of users I'm entering into a grid. The page is getting a category id. I want all of the users to be saved with that category id.
Another thing that would work is if I could get a list of all primary keys, including those for the just-created records, and update all of them with the category id. But it looks like CFGRIDUPDATE doesn't return any information about the rows that were created.
-- original answer removed --
Based on your comment to my original answer, there is now an implied assumption that Category_ID is a foreign key, possibly on a join table, that cannot (for whatever reason) be included in the initial display query--or, that you simply wish to include a dynamic variable into the grid which will be included during inline inserts, without the user intervening (ie. physically preventing them from selecting the Category_ID themselves, but that it will still be dynamic in some capacity, say...by being fed from a URL var).
If correct, I believe the true question leans closer to:
Can a CFGRID update multiple tables/dynamic columns via CFGRIDUPDATE?
Short answer: No
Long answer: Yes, but not via CFGRIDUPDATE--rather, via CFQUERY and a little more work on the CFGRID, via CFC binds and the CFAJAXPROXY.
Solution:
1) You'll need two files for this solution. File #1 is your Component which wraps the query functionality; we'll call it cfgrid.cfc
<cfcomponent>
<cfset this.dsn = "gridexample" />
<cffunction name="getUsers" returntype="any" access="remote" output="false">
<cfargument name="page" />
<cfargument name="pageSize" />
<cfargument name="gridsortcolumn" />
<cfargument name="gridsortdirection" />
<cfset var getUsers = 0 />
<cfquery name="getUsers" datasource="#this.dsn#">
SELECT Users.UserID, Users.FirstName, UserCategories.Category_ID
FROM Users
INNER JOIN UserCategories ON (Users.User_ID = UserCategories.UserID)
<cfif arguments.gridsortcolumn neq "" or arguments.gridsortdirection neq "">
order by #arguments.gridsortcolumn# #arguments.gridsortdirection#
</cfif>
</cfquery>
<cfreturn QueryConvertForGrid(getUsers, page, pageSize) />
</cffunction>
<cffunction name="addNewUser" returntype="string" access="remote" output="false">
<cfargument name="fullname" type="string" required="true" />
<cfargument name="category_id" type="numeric" required="true" />
<cfquery datasource="#this.dsn#">
INSERT INTO Users
(
fullname
)
VALUES
(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.fullname#">
)
</cfquery>
<cfquery name="getPkey" datasource="#this.dsn#">
SELECT Max(User_ID) as PKey
FROM Users
</cfquery>
<cfquery datasource="#this.dsn#">
INSERT INTO UserCategories
(
User_ID,
Category_ID
)
VALUES
(
<cfqueryparam cfsqltype="cf_sql_integer" value="#getPKey.PKey#" />
<cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.category_id#" />
)
</cfquery>
<cfreturn "User Added" />
</cffunction>
<cffunction name="editUser" access="remote">
<cfargument name="gridaction">
<cfargument name="gridrow">
<cfargument name="gridchanged">
</cffunction>
</cfcomponent>
Pay attention to these key pieces of the CFC:
a) getUsers() returns the current user data along with their CategoryID. You'll have to re-write this query to match your schema, but the key takeaway is that this is a data population query, so all the data that's necessary for creating a user should also be present for updating the user as well. This also assumes you only have 1 CategoryID per User (which many developers de-normalize by leaving the CategoryID on the Users table--I'll leave that to your discretion).
b) addNewUser() takes expects the form/grid submission to pass along the new name--as well as the category_id--but we know ahead of time we're not going to be asking that the Category_ID be filled out by the person entering the form/grid data--we'll do that programmatically. The end result is still the same, however--the query is going to need to know both values. For brevity, I've left off <CFTRANSACTION> calls, but bear it in mind--you're about to execute three queries in succession, one of which (the 3rd) depends on dynamic data from the other (the 1st and 2nd)--so you'll need to keep concurrency in mind when you move forward with this type of design.
c) Disregard editUser() for now--you will need to populate it at some point--it simply needs to exist for this demonstration to work.
2) The second file you'll need is the front end--the grid itself, we'll call it cfgrid.cfm.
We'll go through this one, top to bottom, as its quite large, and each chunk of code will need explanation:
<cfparam name="URL.Category_ID" default=4 />
The first line of the template parameterizes a URL variable, which we want to use to programmatically provide behind-the-scenes assignment to new users. Use your own mechanism to supply a dynamic Category_ID as needed.
<cfajaxproxy cfc="cfgrid" jsclassname="dataproxy">
This line causes ColdFusion to create a javascript object named 'dataproxy' and wrap it in a container necessary to provide access the core functions that exist in the CFC you point it to...and in this case, you are pointing it to 'cfgrid', which is our first file mentioned above (cfgrid.cfc). Therefore, you can now comfortably expect that you have a javascript object with getUsers() and addNewUser() methods.
<html>
<head>
<script type="text/javascript" src="/CFIDE/scripts/ajax/ext/package/toolbar/toolbar.js"></script>
Here, you begin your HTML document tags, and include a reference to one of the Ajax libraries included in ColdFusion, the toolbar.js file.
<script type="text/javascript">
var dataproxy = new dataproxy();
dataproxy.setCallbackHandler(handleResult);
function handleResult(response)
{
alert(response);
}
Here, you create a local instance of the dataproxy object (remember above, from the <CFAJAXPROXY> call) and assign a callback handler, which points to another javascript function 'handleResult'. This is the process you employ when dealing with asynchronous communication--a fundamental part of working in Ajax.
function init()
{
grid = ColdFusion.Grid.getGridObject("UserGrid");
var gridHead = grid.getView().getHeaderPanel(true);
var tbar = new Ext.Toolbar(gridHead);
tbar.addButton({text:"Add User", handler:onAdd });
}
This init() function creates the javascript objects necessary to drive communication to the cfgrid. You obtain a reference to the cfgrid via ColdFusion.Grid.getGridObject, and from there, access the grid's header, which allows you to target to toolbar, and add a button "Add User", which you then programmatically decide to call a new function when it is clicked...that function is named "onAdd"...
function onAdd(button,event)
{
ColdFusion.Window.show('addUserWin');
}
Unsurprisingly, here is that onAdd() function, which displays a new window to add a user (its the window that contains the input field for the user's fullname).
Finally, the new AddUserWin Window above is going to need its own function to add a user, since we will need to provide the Category_ID dynamically--as opposed to letting the user supply it. So, addUser() will do just that:
function addUser()
{
var f = document.frmUser;
dataproxy.addNewUser(
f.txtFullname.value,
f.txtCategory_ID.value
);
ColdFusion.Window.hide('addUserWin');
grid.refresh();
}
</script>
</head>
In addUser(), we refer to the <FORM> below by its name (frmUser), and call our javascript proxy object's addNewUser() method--which maps to the CFC. As expected, it'll need to know the values of the new user, so we'll pass it the value of txtFullname and txtCategory_ID. We finish by hiding the window and refreshing the grid.
Remember, we're asynchronous now, so we don't need to read a result and display it--that result will fire via the callback handler assigned above in the handleResult() method.
Now, build the arguments that will feed the population of the CFGRID:
<cfset args = StructNew() />
<cfset args.name = "UserGrid" />
<cfset args.format = "html" />
<cfset args.bindOnLoad = "true" />
<cfset args.bind = "cfc:cfgrid.getUsers({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})" />
<cfset args.selectmode = "edit" />
<cfset args.onchange = "cfc:cfgrid.editUser({cfgridaction},{cfgridrow},{cfgridchanged})" />
Here we:
1. Name the grid "UserGrid" (as we have referred to it by that name in javascript above),
2. Make it render using html,
3. Tell it to bind its data when the page loads,
4. Bind that data via the cfgrid.cfc, calling the getUsers() method (and passing in the current parameters of the cfgrid via its page, pagesize, sortcolumn, and sortdirection values),
5. Make it editable, and
6. Assign an onChange handler, in case we also want to allow the users to be edited. This last part (unfortunately) is necessary, so I was unable to strip it out for this example.
Now, build the <CFFORM> and <CFGRID>:
<cfform>
<cfgrid attributeCollection="#args#">
<cfgridcolumn name="User_ID" display="false">
<cfgridcolumn name="Category_ID" display="false">
<cfgridcolumn name="FullName" header="Full Name">
</cfgrid>
</cfform>
Here, we populate the grid with our arguments specified above, and you'll note we display only the "FullName" field on the grid, yet User_ID and Category_ID are still present, and a part of the dataset; they simply aren't displayed to the front-end.
Last but not least, the window that will pop-up when a user clicks the "Add New User" button, which provides the interface we need to allow user entry, while at the same time, control (behind the scenes) what Category_ID is dynamically supplied:
<cfwindow name="addUserWin" modal="true" resizable="false" title="Add New User">
<form name="frmUser">
<input type="hidden" name="txtCategory_ID" value="<cfoutput>#URL.Category_ID#</cfoutput>" />
<table width="100%">
<tr>
<td>Fullname</td>
<td><input type="text" name="txtFullname" value=""></td>
</tr>
<tr>
<td colspan="2"><input type="button" value="Add User" onclick="javascript:addUser();"></td>
</tr>
</form>
</cfwindow>
This call to CFWINDOW provides the necessary "pop-up" to encapsulate the form. Note that the form name is frmUser, as we have referred to it above in code. Also, note that the name of the fields match (including their case) what are referred to in javascript. This form displays the Fullname field to the user to fill out, while the Category_ID stays hidden, but is still programmatically driven by you--via your URL parameter at the top of this code example. Finally, the button, when clicked, fires the addUser() method, which you'll recall is the one that talks to the javascript object--which in turn--talks to the CFC--and commits your data to the database.
Finally, just before you complete this template, don't forget to fire your init() javascript function!
<cfset ajaxOnLoad("init")>
</html>
Hope this helps.
Adapted from CRUD with cfgrid html format (Source: Anuj Gakhar)
There is another way. It involves handling directly the form variables which are posted by CFGRID. Here's some example code:
form.cfm:
<cfform method="post" action="post.cfm">
<cfoutput><input type="hidden" name="ParentID" value="#ParentID#"></cfoutput>
<cfgrid format="html" name="GridData" query="Records" insert="yes" delete="yes" selectmode="edit">
<cfgridcolumn name="RecordID" display="no">
<cfgridcolumn name="RecordName" width="150" header="Name" headeralign="left" dataalign="left" select="Yes" display="Yes">
<cfgridcolumn name="RecordColor" width="150" header="Color" headeralign="left" dataalign="left" select="Yes" display="Yes">
</cfgrid>
<br />
<input type="submit" value="Save Records" />
</cfoutput>
</cfform>
then in post.cfm
<cfif isDefined("GridData.RowStatus.Action") and isArray(GridData.RowStatus.Action)>
<cfloop from="1" to="#ArrayLen(GridData.RowStatus.Action)#" index="i">
<cfswitch expression="#GridData.RowStatus.Action[i]#">
<cfcase value="I">
<cfquery name="Records_INSERT" datasource="#request.maindatasource#" blockfactor="100">
INSERT INTO Records (RecordName, RecordColor, RecordParent)
VALUES (
<cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordName[i])#">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordColor[i])#">,
<cfqueryparam cfsqltype="cf_sql_integer" value="#Val(ParentID)#">
)
</cfquery>
</cfcase>
<cfcase value="U">
<cfquery name="Records_UPDATE" datasource="#request.maindatasource#" blockfactor="100">
UPDATE Records
SET
RecordName = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordName[i])#">,
RecordColor = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(GridData.RecordColor[i])#">
WHERE
RecordID=<cfqueryparam cfsqltype="cf_sql_integer" value="#GridData.original.RecordID[i]#">
</cfquery>
</cfcase>
<cfcase value="D">
<cfquery name="Records_DELETE" datasource="#request.maindatasource#" blockfactor="100">
DELETE
FROM Records
WHERE
RecordID=<cfqueryparam cfsqltype="cf_sql_integer" value="#GridData.original.RecordID[i]#">
</cfquery>
</cfcase>
</cfswitch>
</cfloop>
</cfif>
Related
I am working with ColdFusion and am new to the language. I want to perform a database operation with the given value and return the result via ajax response, when the onBlur event of a textbox is triggered. Please check my code below
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#username").blur(function() {
alert("This input field has lost its focus.");
var userNameVal = $(this).val();
if(userNameVal != "") {
$.get("myajax.cfc?method=getuser&userName=userNameVal", function(res) {
$("#userid").val=res;
}, "JSON");
}
});
});
</script>
<input type='textbox' name='username' id='username' />
<input type='hidden' name='userid' id='userid'/>
myajax.cfc:
<cfcomponent>
<cffunction name="getuser" access="remote" returntype="Integer">
<cfargument name="userName" type="string" required="yes">
<cftry>
<cfquery name="getUser" datasource="ajax_example">
select USER_ID
from user u
where u.firstname=userName;
<cfqueryparam value = "#url.userName#" cfsqltype="cf_sql_varchar">
</cfquery>
<cfcatch>
<cfoutput>
#cfcatch.Detail#<br />
#cfcatch.Message#<br />
#cfcatch.tagcontext[1].line#:#cfcatch.tagcontext[1].template#
</cfoutput>
</cfcatch>
</cftry>
<cfreturn getUser.USER_ID/>
</cffunction>
</cfcomponent>
From my ajax.cfc response I want to return USER_ID to my ajax call. How can I do this?
You need to pass the actual value of the variable named userNameVal in the query string. Like this:
$.get("myajax.cfc?method=getuser&userName="+userNameVal, function(res) {
$("#userid").val=res;
}, "JSON");
And as #Dan suggested, the way you are using cfqueryparam, is wrong. It should be done like this:
<cfquery name="getUser" datasource="ajax_example">
select USER_ID
from user u
where u.firstname=<cfqueryparam value = "#arguments.userName#" cfsqltype="cf_sql_varchar">
</cfquery>
You have this code:
where u.firstname=userName;
<cfqueryparam value = "#url.userName#" cfsqltype="cf_sql_varchar">
This is not valid sql. The semi-colon terminates the command and ColdFusion will throw an error because the cfqueryparam tag comes afterwards.
You also have this query in a cftry block. The cfcatch code outputs data. If you were calling this function from ColdFusion code, you would see the cfcatch information in your web browser. However, you are calling it with ajax. It's outputting to a black hole. Also, you are getting no ColdFusion error because of the try/catch. Plus the cfcatch block does not include a cfreturn tag so nothing gets returned to javascript.
Another error is that you are using the wrong scope in your query. This:
value = "#url.userName#"
should be this:
value = "#arguments.userName#"
You are attempting to do too many things at once. I suggest calling your method with ColdFusion until you get it working properly. Then call it with ajax.
I'm working with ColdFusion Server version 8,0,0,176276.
I'm trying to add an autosuggested form field, with asynchronous population through a cfc. I'm using http://www.forta.com/blog/index.cfm/2007/5/31/coldfusion-ajax-tutorial-1-autosuggest for inspiration and syntax.
The autosuggest field works fine if I use a static query (as in Forta's first example). The cfc is successfully returning an array when not used in the form field.
But when I use the cfc for autosuggest, there are no suggestions provided.
I can't see the contents of the input field with "view source," but if I do "inspect element" on the field in Chrome, I can see a div with class="yui-ac-bd" and a ul under it. The list items in the ul are empty when using the cfc, whereas when I use a static query, the list items contain the array members.
Here's the code on my page:
<cfform>
<cfinput type="text" name="JobP"
autosuggest="cfc:autosuggest.AutoSuggest({cfautosuggestvalue})">
</cfform>
And here's autosuggest.cfc:
<cfcomponent output="false" >
<cffunction name="AutoSuggest" access="remote" returntype="array">
<cfargument name="ObjectType" required="false" default="JOBP">
<cfset var result=ArrayNew(1)>
<cfquery name="Objects" datasource="UC4MP">
SELECT oh_name
FROM uc4.oh
WHERE oh_otype = '#ObjectType#'
AND oh_deleteflag = 0
AND oh_lastdate > sysdate - 90
AND oh_client = 1000
and oh_name like 'A%'
ORDER BY oh_name
</cfquery>
<cfloop query="Objects">
<cfset ArrayAppend(result,oh_name)>
</cfloop>
<cfreturn result>
If I put the following code on my page, it outputs the array with the desired contents:
<cfinvoke component="autosuggest" method="AutoSuggest" returnVariable="result">
cfdump var="#result#">
I don't use jQuery yet; most of my Google results for CF autosuggest have involved jQuery and I haven't been able to wade through them for relevance to my problem. Just in case that was going to be your suggestion.
Thank you all for your advice! I had not known there was a separate ajax debugger, the output of which immediately made the problem clear:
info:http: Invoking CFC: /rd/autosuggest.cfc , function: AutoSuggest ,
arguments: {"ObjectType":"A"}
My cfc arguments didn't include the autosuggest itself, so the string passed to the input field was being interpreted as "ObjectType" (the first argument) and used in the query. Since there are no records where oh_otype = 'A', the result was always empty.
I updated my cfc's arguments to
<cfargument name="ObjectType" required="yes" default="JOBP">
<cfargument name="autosuggest" required="yes">
and the invocation to
<cfinput type="text" name="JobP"
autosuggest="cfc:autosuggest.AutoSuggest('JOBP',{cfautosuggestvalue})">
...works perfectly now.
If i remember correctly when I did this some years ago, I had to create a virtual directory in Apacahe and set permisions using the following directives. You can apply the same to IIS if you are working in that environment. That should get it going for you.
Alias /CFIDE "/opt/coldfusion9/wwwroot/CFIDE"
<Directory "/opt/coldfusion9/wwwroot/CFIDE">
allow from all
Options FollowSymLinks
Since then I have been using the typehead javascript from bootstrap 2. Much cleaner and easier to style. You can still use your cfc to call the data and I am including the code to clean it up for typehead.
<cfinvoke component="autosuggest" method="AutoSuggest" returnVariable="result">
<cfset mylist = ArrayToList(result, ",")>
<cfset mylist=ValueList(ShowKey.keyword)>
<cfset mylist = jSStringFormat(#mylist#)>
<input name="keyword" id="keyword" type="text" data-provide="typeahead" data-items="10" data-source='["<cfoutput>#replace(mylist,',','","','ALL')#</cfoutput>"]'/>
I am using CF10. I have a Select:
<cfselect name="company" id="company" query="qcompany" display="placename" value="placeid" queryposition="below">
<option value="0">--Select--
</cfselect>
I have another cfselect that is bound to the first:
<cfselect name="People" bind="cfc:schedule.GetPeopleArray({company})" ></cfselect>
I cannot get the second cfselect to display any results. To test whether or not I am receiving data from my component (which I will display at the bottom), I bound a text box:
<cfinput name="test" bind="cfc:schedule.GetPeopleArray({company})" bindonload="false"/>
This text box is displaying the results of the call to my component every time, but the cfselect never displays anything.
What could I possibly be doing wrong?
I have tried returning arrays and queries from my component. No help. I have tried adding display and value attributes to the second cfselect. No help.
Here is my component:
<cfcomponent output="false">
<cffunction name="GetPeopleArray" access="remote" returnType="array" output="false">
<cfargument name="company" type="string" >
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(2)>
<cfset var i=0>
<cfquery name="qEmployee" datasource="texas" >
SELECT 0 as personid,'Select Person' as fullname,0 as sortorder
UNION
SELECT p.personid ,concat(firstname,' ',lastname) as fullname,3 as sortorder
FROM person p
INNER JOIN placeperson pp
ON p.personid=pp.personid
where personstatus='ACT'
and pp.placeid=#arguments.company#
order by sortorder,fullname
</cfquery>
<!--- Convert results to array --->
<cfloop index="i" from="1" to="#qEmployee.RecordCount#">
<cfset result[i][1]=qEmployee.personid[i]>
<cfset result[i][2]=qEmployee.fullname[i]>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
</cfcomponent>
Ultimately, you may want use jQuery anyway, but FWIW your existing code worked fine with CF10. (The only change was removing the JOIN for simplicity) So either you are using different code, or there is something else going on we are unaware of ..
Truthfully the Ajax functionality does have some "quirks". However, you should not have any problem with a simple case like this. Aside from adding a text field, what other debugging or troubleshooting steps did you perform? What I usually recommend is:
Test the CFC independently first. Access it directly in your browser with a variety of sample values:
http://localhost/path/to/schedule.cfc?method=GetPeopleArray&company=someValue
I did this with the original code and discovered an error occurred when the company value is not numeric, like an empty string. (I suspect that might have been the problem) You can prevent that error by substituting an invalid ID like 0 instead. Note, be sure to use cfqueryparam to prevent sql injection.
AND pp.placeid = <cfqueryparam value="#val(arguments.company)#"
cfsqltype="cf_sql_integer">
Enable the CF AJAX debugger in the CF Administrator. Then append ?cfdebug to your test script so you can view the console and check for problems/errors.
http://localhost/path/to/yourTestForm.cfm?cfdebug
Again, I did this after tweaking the query. But there were no errors. Your existing cfform code worked perfectly.
Usually those two steps are enough to pinpoint any problems. If not, make sure your Application.cfc file (if you are using one) is not interfering with the Ajax request. That is a common gotcha. Test the code in a separate directory that is outside any Application files.
EDIT: Also, you may as well set bindonload="false" for the select list too. Since you do not want to call the function when the page first loads. Only when the user selects something from the list.
I am buliting an add/edit user form, when the page is accessed there is an if statement which detects if we are editing a current user or addindg a new user by a url id
<cfif isDefined('URL.id')>
<cfquery name="getSquadMember" datasource="#application.datasource#">
SELECT * from squad WHERE id=#URL.id#
</cfquery>
<cfset #name#=#getSquadMember.athlete_name# />
<cfelse>
<cfset SESSION.squad = structNew()>
<cfparam name="SESSION.squad.name" default="">
</cfif>
That is fine but the problem comes in evaluting if the session or value exists, I get an error
<cfinput class="text" name="name" type="text" id="name" value ="#IIf(IsDefined('name'), DE('#name#'), DE("#SESSION.squad.name#"))#" required="yes" />
Element squad.name is undefined in session. Why is it eveluating if session exists when the first condition is met?
Thanks,
R.
First up - if you can possibly avoid using iif(), then do so. It causes many more headaches than it has ever solved...
However, note the following from the ColdFusion documentation on iif():
If a variable is undefined, ColdFusion throws an error when it processes this function. The following example shows this problem:
#IIf(IsDefined("Form.Deliver"), DE(Form.Deliver), DE("no"))# This returns "Error resolving parameter FORM.DELIVER".
To avoid this problem, use the DE and Evaluate functions in code such as the following:
#IIf(IsDefined("Form.Deliver"), Evaluate(DE("Form.Deliver")), DE("no"))# This returns "no"; ColdFusion does not throw an error.
Or, if you're on CF9 (which supports ternary operators):
<cfinput class="text" name="name" type="text" id="name" value ="#IsDefined('name') ? name : SESSION.squad.name#" required="yes" />
Is there a reason as to why you need to have two different variable names for the same item? Could you just do:
<cfif isDefined('URL.id')>
<cfquery name="getSquadMember" datasource="#application.datasource#">
SELECT * from squad WHERE id=<cfqueryparam value="#URL.id#" cfsqltype="CF_SQL_INTEGER" />
</cfquery>
<cfset name= getSquadMember.athlete_name />
<cfelse>
<cfset squad = structNew()>
<cfset name = "" />
</cfif>
<input type="text" name="name" id="name=" value="#name#" />
Which would then in turn remove the need for the iff statement
HTH
J
Couple of issues:
1)
<cfquery name="getSquadMember" datasource="#application.datasource#">
SELECT * from squad WHERE id=#URL.id#
</cfquery>
You're asking for a SQL injection here. Use cfqueryparam
2)
<cfset #name#=#getSquadMember.athlete_name# />
It's your second post where I notice weird use of #
It should be as Jason wrote it:
<cfset name = getSquadMember.athlete_name />
3) As for your question:
<cfinput class="text" name="name" type="text" id="name" value="#IIf(IsDefined('name'), DE('#name#'), DE("#SESSION.squad.name#"))#" required="yes" />
This way is not really readable.
Set some variable for the value first.
Second thing - you don't need to put the variables in DE like this, this will do:
DE(name)
And as you're using cfinput the whole thing probably needs to be correct. And another issue - you don't really need to use cfinput there. Normal HTML input will do and save you some CF parsing.
The problem you are seeing is that IIF() has to evaluate all parts of the statement.
You can't really use it for checking if a variable is defined or not as it will always try to evaluate the contents of both the true and false responses.
As long as you bear this in mind when using IIF() there's no problem with using it. Just keep it simple and don't try to use it when a variable might not exist.
I was going to point out the other issues with your code, but the other answers have already done a good job of covering these.
I have CFINPUT text boxes (type= datefield) that are bound to a cfgrid.
When a row is selected the input display from the grid's datastore.
What I would like to do is not use the edit functionality of the grid since there is much coding involved with other controls to render the input boxes and other controls for my page.
I would like that when a change in made in the input text box the cfc is run to insert or update to the database.
Any suggestions?
I blv you should invoke cfc in the onchange of the cfinput. The code should look like:
function edit(eqp)
{
Do what ever you like
}
The name of the cfgrid is equipmentList
You could use cfbind to do this, try something like this,
<cfinput name="inputName" type="text">
<cfinput name="rowID" type="hidden" value="#rowID#">
<cfdiv bind="url:anotherPage.cfm?IName={inputName#keyup}&RId={rowID}" bindOnLoad="false">
----In anotherPage.cfm----
<cfinvoke
component="CFC_name"
method="Method_Name">
<cfinvokeargument name="I_Name" value="#trim(IName)#"/>
<cfinvokeargument name="R_ID" value="#trim(RId)#"/>
</cfinvoke>
----In CFC---->
<cffunction name="CFC_name" access="remote">
<cfargument name="I_Name" type="string" required="yes">
<cfargument name="R_ID" type="string" required="yes">
<cfquery name="Q1" datasource="ds">
UPDATE Tbl1
SET Col1=<cfqueryparam value="#arguments.I_Name#" cfsqltype="cf_sql_varchar">
WHERE ID = #arguments.R_ID#
</cfquery>
</cffunction>
you could Bind by using, #keyup, #keydown, #change, #click etc.