Accessing Query Data from CFC Function - coldfusion

Here is what I am up against: I am trying to change the content of a CFDIV based on the selection from a CFSelect box.
To do this I have bound the CFDiv to a CFC and I am trying to return two columns from my query that is executed in that CFC; Alert_Status AND Alert_Priority. These values will be queried based on a selection from the CFSelect box in my CFM page. Company_Name is the value passed to the CFC from the selection in the CFSelect box. Once the query in the CFC is run, I would like to display the results in a DIV on that same CFM page as the select box.
Here is the CFC:
<!---First Slect Box --->
<cffunction name="getData" access="remote" returntype="query">
<cfoutput>
<!--- Function to get data from datasource --->
<cfquery name="data" datasource="#datasource#">
select company_name, customer_id
from customer_table
where status <> '0'
order by company_name
</cfquery>
</cfoutput>
<!--- Return results --->
<cfreturn data>
</cffunction>
<cffunction name="getDetail" access="remote" returnType="string">
<cfargument name="company_name" type="any" required="true">
<!--- localize function variables --->
<cfset var dataDetail = "">
<cfoutput>
<cfquery name="dataDetail" datasource="#datasource#">
SELECT tax_rate
FROM customer_table
<!--- adjust cfsqltype if needed --->
WHERE company_name = <cfqueryparam value="#ARGUMENTS.company_name#" cfsqltype="cf_sql_varchar">
</cfquery>
</cfoutput>
<cfreturn dataDetail.tax_rate>
</cffunction>
<cffunction name="getAlerts" access="remote" returnType="query">
<cfargument name="company_name" type="any" required="true">
<!--- localize function variables --->
<cfset var alertDetail = "">
<cfoutput>
<cfquery name="getID" datasource="#datasource#">
select customer_id
from customer_table
where company_name = <cfqueryparam value="#ARGUMENTS.company_name#" cfsqltype="cf_sql_varchar">
</cfquery>
<cfquery name="alertDetail" datasource="#datasource#">
SELECT *
FROM customer_alerts
<!--- adjust cfsqltype if needed --->
WHERE customer_id = <cfqueryparam value="#getID.customer_id#" cfsqltype="cf_sql_varchar"> AND alert_status = 'on'
</cfquery>
</cfoutput>
<cfreturn alertDetail>
</cffunction>
I am trying to display the query results for the query AlertDetail in a div on my main page.
Here is the portion of my CFM page that relates to this CFC:
<cfdiv name="test" id="test" type="text" bind="cfc:cfcs.taxdata.getAlerts({company_name})" bindonload="true" bindattribute="value" rows="2" cols="2" readonly="yes"></cfdiv>
Any help would be greatly appreciated. Thanks.
-Brian

Let's step back for a moment. I see your goal and sometimes using CFDiv only complicates things. I would just use AJAX. I wasn't sure what you meant by "two columns" so the current example I am sending you only shows one function being returned. Adding the second will be pretty easy to replicate.
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
// populate the dropdown
$.ajax({
type: "GET",
url:"cfcs/taxdata.cfc?method=getData",
dataType: "json",
success: function (data) {
$("#formSelect").html("");
// may need tweeking depending on how you are outputting your query.
$.each(data,function(i,obj)
{
var div_data="<option value="+obj+">"+obj+"</option>";
$(div_data).appendTo('#formSelect');
});
}
});
// on change of dropdown value return the cfc data into the div
$("#formSelect").change(function() {
var selectValue = $("#formSelect").val();
$.ajax({
type: "GET",
url:"cfcs/taxdata.cfc?method=getAlerts",
dataType: "json",
data: {
company_name: selectValue
},
success: function (data) {
$("#test").html(data);
}
});
});
</script>
</head>
<body>
<form>
<select id="formSelect">
</select>
</form>
<div id="test"></div>
</body>
Also, below is how you can add multiple results to the <div>
<!-- Use multiple AJAX calls to each function. Have them return in separate divs within the main div. -->
<div id="test">
<div id="query1"></div>
<div id="query2"></div>
<div id="query3"></div>
<!-- You can also do paragraph tags. JQuery only looks for the ID or class -->
<p id="query4"></p>
</div>
Option Two
<!--
In your ajax instead of using $("#test").html(data); you can use appentTo() for each AJAX call
-->
success: function (data) {
$(data).appendTo('#test');
}

Related

Display Events in Fullcalendar underneath calendar?

I am having a hard time to do this. The calendar Displays the events in the calendar however, I would like to be able to list the events as well below the calendar so you can see the full name of the events that are in the current month. I have the following code(I am using coldfusion and Mura and I am new to both):
<cffunction name="MultipleFeaturedEvents">
<cfargument name="feedName" type="string" default="702771E7-155D-0201-11DF8865B175735F"/>
<cfargument name="maxMonths" type="numeric" default="3" />
<cfargument name="groupDailyEvents" default="true" />
<cfscript>
var rs = '';
var subRS1 = '';
var local = {};
local.listIDs = '';
local.util = $.getCalendarUtility();
local.rsItems = local.util.getCalendarItems(calendarid=arguments.feedName, start=Now(), end=DateAdd('m', val(4), Now()));
var qoq = new Query();
qoq.setDBType('query');
qoq.setAttributes(rs=local.rsItems, maxRows=val(1));
qoq.setSQL('
SELECT *
FROM rs
ORDER BY displaystart ASC
');
var qoqResult = qoq.execute().getResult();
local.it = $.getBean('contentIterator').setQuery(qoqResult);
</cfscript>
<cfsavecontent variable="local.str">
<cfoutput>
<cfset ctr=1 />
<!---<div>#local.it.hasNext()#</div>--->
<cfloop condition="(local.it.hasNext()) AND (ctr LT 4)">
<cfset local.item = local.it.next() >
<cfif not ListFind(local.listIDs, local.item.getValue('contentid'))>
<cfif ctr eq 1>
<!--- TODO: set a default image if no image is available --->
<div class="hidden-xs col-md-2">
<p class="upcoming-events-image"><img src="#local.item.getImageURL()#" alt="#HTMLEditFormat(local.item.getTitle())#"> </p>
</div>
<div class="col-md-offset-0 col-md-4" id="featured-event">
<h3>#HTMLEditFormat(local.item.getMenuTitle())#</h3>
<i class="fa fa-calendar fixIconCal"></i>
<!---#local.item.getDisplaystart()#--->
#LSDateFormat(local.item.getValue('displayStart'), "mmm d, yyyy")#
<cfquery dbtype="query" name="subRS1">
select *
from rsItems
where rsItems.contentid = <cfqueryparam value="#local.item.getValue('contentid')#" />
</cfquery>
<cfif subRS1.recordcount gt 1>
<!--- end date --->
<cfset enddate = ListLast(ValueList(subRS1.displaystop)) />
<cfif IsValid('date', enddate)>
- #LSDateFormat(enddate)#
</cfif>
</cfif>
<br />
<i class="fa fa-clock-o"></i>
#timeFormat(local.item.getValue('displayStart'), "h:mm tt")# - #timeFormat(local.item.getValue('displayStop'), "h:mm tt")#
<br />
<i class="fa fa-map-marker"></i>
Location Information
<!--- Summary --->
<div class="featured-event-summary">
<cfif Len(local.item.getValue('summary'))>
#local.item.getValue('summary')#
</cfif>
</div>
</div>
<cfelse>
</cfif>
</cfif>
</cfloop>
</cfoutput>
</cfsavecontent>
<cfreturn local.str />
</cffunction>
Below is what I am trying to do:
Any help would be appreciated. Thanks
Don't know if you can use plain JS (I don't know ColdFusion), but typically you can retrieve all FullCalendar events by invoking:
$('#calendar').fullCalendar('clientEvents')
Which returns array of Events, then you can iterate over it and render some list.
Hope this helps.
EDIT:
So maybe something like
$('#calendar').fullCalendar('clientEvents', function(ev) {
//will loop for each event you have in the calendar
console.log(ev); //event
});
And you can use something like:
$('#calendar').fullCalendar('clientEvents', function(ev) {
$('.your-list-container').append('<div>' + ev.title + '</div>');
});
this is js code , hope its help you ..
//get the start and the end of the current view
var startDate = $('#idOfCalendar').fullCalendar('getView').start;
var endDate = $('#idOfCalendar').fullCalendar('getView').end;
var eventsNames= new Array();
var todaysEvents = $('#idOfCalendar').fullCalendar('clientEvents', function (event) {
if (event.start >= startDate && event.start <= endDate
|| event.end >= startDate && event.end <= endDate) {
eventsNames.push(event.title)
//take what do you whant from the event object
return true;
}
});

When using Cfmail is it possible to see the email before sending?

From examples I seen online It seems using cfmail is only to send emails automatically.
Would it be possible to see the email HTML text before sending it the the recipient?
In other words I would be able to change the 'TO:' email part.
Is this possible or cfmail only works sending emails automatically?
Example code of cfm file:
<cfquery....>
select ...
</cfquery>
<cfmail query="test"
to=""
from="mail#mail.com"
.....
type="html">
here is test
<cfoutput>
<p>#data</p>
</cfouput>
</cfmail>
I would do something like this.
<cfquery....>
select ...
</cfquery>
<!--- Save your content to a variable --->
<cfsavecontent variable="content">
here is test
<cfoutput>
<p>#data#</p>
</cfouput>
</cfsavecontent>
<!--- Output that content into a div so the user can see it--->
<div id="email-content">
<cfoutput>#content#</cfouput>
</div>
<button onclick="sendEmail()">send</button>
<!--- When the user clicks send call a JS function --->
<!--- Use ajax to call a send function and use your email content --->
<script type="text/javascript">
function sendEmail()
{
var emailContent = $('#email-content').html();
$.ajax({
type: 'POST',
url: "yourCFCfileToSendEmail?method=sendEmail&content=" + emailContent ,
success: function(){
console.log("email sent");
}
});
}
</script>
<!--- An example of what your email function would look like in the cfc . --->
<cffunction name="sendEmail" access="remote" returntype="string" returnformat="plain">
<cfargument name="toEmail" type="string" required="true">
<cfargument name="fromEmail" type="string" required="true">
<cfargument name="subject" type="string" required="true">
<cfargument name="content" type="string" required="true">
<cfargument name="replyTo" type="string" required="false">
<cfset attributes = decodeParams(params)>
<cfparam name="arguments.replyTo" default="#arguments.fromEmail#">
<cfif NOT Len(Trim(arguments.replyTo))>
<cfset arguments.replyTo = arguments.fromEmail>
</cfif>
<cfmail to="#arguments.toEmail#"
from="#arguments.fromEmail#"
subject="#arguments.subject#"
replyto="#arguments.replyTo#"
type="html">
<h1>#arguments.subject#</h1>
#content#
</cfmail>
</cffunction>
I have not tested this. It will take some tweaking but should point you in the right direction.
This answer is very similar to Will's. It does the job with a bit less code.
Assuming the user submits a form, start with this:
session.mailto = form.mailto;
session.mailfrom = form.mailfrom;
Then do this:
<cfsavecontent variable = "session.mailbody">
code
</cfsavecontent>
Present this to the user:
<a href="javascript:void(0)"
onclick="Emailwin=window.open('SendMail.cfm','thewin',
'width=500,height=500,left=30,top=30');">
<button type="button">Send Mail </button>
SendMail.cfm looks like this:
<cfmail to="#session.mailto#" from="#session.mailfrom#"
subject = "something" type="html">
#session.mailbody#
</cfmail>
<h3>Your mail has been sent. This window will close in 2 seconds.</h3>
<script language="javascript">
winClose=window.setTimeout("window.close()",2000);
</script>
The code which I copied was written a long time ago in an envrionment with locked down computers. If I were to do it again, I would probably use hidden form fields instead of session variables. They are more likely to change unexpectedly these days.
If you are coding for the general public, bear in mind that the user might change his browser preferences to prevent the new window from opening.

ColdFusion autosuggest in text field is not responsive

I have a text field that I want to autosuggest values based on a query. I have a main file along with a separate file (getdata.cfc) that holds my query.
Here is the text field portion of my main file:
<cfinput name="search_query" autosuggest="url:getdata.cfc?suggestvalue={cfautosuggestvalue}" maxResultsDisplay="10" showAutoSuggestLoadingIcon="true" size="10" />
Here is the code in getdata.cfc:
<cfcomponent>
<cffunction name="get_data" access="remote" output="false">
<cfargument name="suggestvalue" required="true">
<cfquery name="get_data" datasource="#application.DSN#">
SELECT DISTINCT myItem
FROM myTable
WHERE myItem LIKE <cfqueryparam value="#suggestvalue#%"
cfsqltype="cf_sql_varchar">
ORDER BY myItem
</cfquery>
<cfif get_data.recordCount eq 1>
<cfreturn ",#get_data.myItem#">
<cfelse>
<cfreturn ValueList(get_data.myItem)>
</cfif>
</cffunction>
</cfcomponent>
The text field shows up fine, but when I type a word no autosuggest values show up. Nothing happens. The text is just displayed as I type it.
Any suggestions? Thank you!
I switched away to using jquery plugins from a lot of CF stuff, but here is an example I have that works in some old production code
<cfinput type="text" name="email" id="email" autosuggest="cfc:cfc.users.lookupEmail({cfautosuggestvalue})" maxresultsdisplayed = "25">
<cffunction name="lookupEmail" access="remote" returntype="array">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(1)>
<!--- Do search --->
<cfquery name="data" datasource="datasource" maxrows="25" cachedwithin="#CreateTimeSpan(0,0,30,0)#">
SELECT distinct email
FROM users
WHERE email LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.search#%">
ORDER BY email
</cfquery>
<!--- Build result array --->
<cfloop query="data">
<cfset ArrayAppend(result, email)>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
maybe this helps
also make sure you have your cfform tags around your form, and make sure that your /cfide folder is mapped to your website.
looking at your code and comparing it... it may be the way your calling the cfc (filename)
try: autosuggest="cfc:getdata.get_data.({cfautosuggestvalue})"

Binding Data to a CFTEXTAREA

I am populating a cfselect box using the bind attribute. I'd like to be able to make my selection from the two drop downs and then populate a CFTEXTAREA based on that selection. I thought I could just issue a similar bind attribute command but the textarea outputs:
[object Object]
CF8 documentation says that this is possible? What am I missing?
Form Code:
<cfselect name="descriptionDD" value="description" bind="cfc:cfcs.menudata.getData()" bindonload="true" />
<cftextarea name="detailDD" value="service_detail" bind="cfc:cfcs.menudata.getDetail({descriptionDD})" bindonload="true" />
CFC Code:
<cfcomponent>
<!---First Select Box --->
<cffunction name="getData" access="remote" returntype="query">
<!--- Function to get data from datasource --->
<cfquery name="data" datasource="ezpay">
select description
from service_descriptions
order by description
</cfquery>
<!--- Return results --->
<cfreturn data>
</cffunction>
<!---Second Select Box --->
<cffunction name="getDetail" access="remote" returnType="query">
<cfargument name="description" type="any" required="true">
<cfquery name="dataDetail" datasource="ezpay">
SELECT service_detail
from service_descriptions
WHERE description = '#ARGUMENTS.description#'
ORDER BY ID ASC
</cfquery>
<cfreturn dataDetail>
</cffunction>
</cfcomponent>
but the textarea outputs: [object Object]
That usually means you are returning a complex object where a simple string is expected instead. [object Object] is essentially the string representation of the complex object (in your case a query).
TextArea's are designed to display a single value. So your bind function should return a string, not a query object.
<cffunction name="getDetail" access="remote" returnType="string">
<cfargument name="description" type="any" required="true">
<!--- localize function variables --->
<cfset var dataDetail = "">
<cfquery name="dataDetail" datasource="ezpay">
SELECT service_detail
FROM service_descriptions
<!--- adjust cfsqltype if needed --->
WHERE description = <cfqueryparam valu="#ARGUMENTS.description#" cfsqltype="cf_sql_varchar">
ORDER BY ID ASC
</cfquery>
<cfreturn dataDetail.service_detail>
</cffunction>

Nesting queries in CF

I'm using this code to display a list of platforms. If a platformID was specified upon entering the page, I would like to create a list of genres underneath the specified platform.
browse.cfm was accessed via a link that specified a platformID of 1
browse.cfm will list all available platforms
browse.cfm will now list all available genres under platformID of 1.
<ul>
<li>Browse</li>
<cfoutput query="qGetPlatforms">
<li>
#qGetPlatforms.pName#
<cfif URL.platformID EQ qGetPlatforms.platformID>
<ul>
<cfoutput query="qGetGenres">
<li>#qGetGenres.gName#</li>
</cfoutput>
</ul>
</cfif>
</li>
</cfoutput>
</ul>
By using this approach, however, I'm getting an invalid nesting configuration. How do I fix this? Or is there another approach to achieve the same idea?
Thanks
MY queries:
<!---Get platforms--->
<cffunction
name="fGetPlatforms"
access="public"
returntype="query"
output="false"
hint="I get all the platforms">
<!---Local var--->
<cfset qGetPlatforms = "">
<!---Database query--->
<cfquery name="qGetPlatforms" datasource="#REQUEST.datasource#">
SELECT
platforms.platformID,
platforms.platformName AS pName
FROM
platforms
</cfquery>
<cfreturn qGetPlatforms>
</cffunction>
<!---Get genres--->
<cffunction
name="fGetGenres"
access="public"
returntype="query"
output="false"
hint="I get all the genres">
<!---Local var--->
<cfset qGetGenres = "">
<!---Database query--->
<cfquery name="qGetGenres" datasource="#REQUEST.datasource#">
SELECT
genres.genreID,
genres.genreName AS gName
FROM
genres
</cfquery>
<cfreturn qGetGenres>
</cffunction>
You can use <cfloop query="qGetGenres"></cfloop>, they can be nested.
IMO, using cfoutput for looping over the queries is old style and should be avoided. Use cfoutput for output, cfloop for looping and you'll have more readable code.
more food for thought is to use an inner join between the two tables, combine and retrieve everything in one query and then use cfoutput's group attribute to display the results:
<cfset URL.platformID = int(val(URL.platformID))>
<cfquery name="getPlatformsAndGenres" datasource="#REQUEST.datasource#">
SELECT
p.platformID AS platformID
,p.platformName AS pName
,g.genreID AS genreID
,g.genreName AS gName
FROM
platforms p
INNER JOIN genres g
ON p.platformID = g.platformID
WHERE
p.platformID = <cfqueryparam cfsqltype="cf_sql_integer" value="#URL.platformID#">
ORDER BY
pName
,genreName
</cfquery>
Once you have everything in one query, you can use <cfoutput query="getPlatformsAndGenres" group="pName">
to lessen your code:
<ul>
<li>Browse</li>
<cfoutput query="getPlatformsAndGenres" group="pName">
<li>
#pName#
<ul>
<cfoutput>
<li>#gName#</li>
</cfoutput>
</ul>
</cfif>
</li>
</cfoutput>
</ul>