Sorry for the obtuse title, but I wanted to demonstrate how Spry handles conditionals. What do I mean by that? So far all of my examples have mainly shown how to dump data into a table. While this is useful, sometimes you want to filter the data being shown. I've shown examples with filtering for pagination and keyword filtering, but there are other ways to do conditional type operations with Spry.
Let's first take a look at a quick way to filter out data. In my last Spry article, I showed you how you could quickly add a RSS based Spry pod to your site. The pod dumped all the entries from the MXNA XML feed. What if you wanted to filter it by certain categories? Here is the code for that:
<span spry:repeat="mydata">
<span spry:if="'{dc:subject}'.indexOf('ColdFusion') != -1;">
<a href="{link}"><span spry:content="{title}"></span></a><br>
</span>
</span>
What you want to focus in on is the spry:if condition. Basically, the data inside the block will not be displayed unless the condition matches. You use a JavaScript expression for your condition. In my example, I used:
'{dc:subject}'.indexOf('ColdFusion') != -1;
Spry will replace the {dc:subject} at runtime, and then do an indexOf to see if "ColdFusion" is in the category list. (Notice I didn't do a direct comparison as the category may have been "Flash, ColdFusion".
You can see this example running here. Now for the next example. What if you wanted to do a simple If/Then type check with Spry? Spry supports a spry:choose command which acts much like an If/Else or Case type block.
Consider this example:
<tr spry:repeat="mydata">
<td>{name}</td>
<td>
<div spry:choose="spry:choose">
<div spry:when="'{debt}' > 100000" class="bad">{debt}</div>
<div spry:when="'{debt}' > 50000" class="warning">{debt}</div>
<div spry:default="spry:default">{debt}</div>
</div>
</td>
</tr>
Each spry:when inside the choose block will be checked. If a condition is matched, the content inside is run. You can also use a spry:default block to handle a final condition. Check it out at this example. I use it to flag debts that are either very high, or close to getting high.
Archived Comments
Thanks Ray. It works. Man, I'm really liking Spry.
I posted this one on the forums. Have you tried the double sort? It works good:
ds.sort(['col1','col2']);
But now I want to set one to "toggle" and the other to always "ascending". I can't figure this one out. This gives an error:
ds.sort(['col1','col2'],['toggle','ascending']);
Any ideas?
I've been following your blog for some time now, Ray, and I wanted to thank you for your excellent demos and examples on Spry.
I've been loving Spry myself and I've starting using it in our database web applications.
In regards to Spry conditionals, I'd like to embed the choose/when or if constructs inside a single tag so I can do something like this:
<cfinput spry:if="{ds_CurrentRowID} < 0" value="#DateFormat(today,'m/d/yyyy')#" spry:if="{ds_CurrentRowID} >= 0" value ="{dtmcontactdate}" ... />
I know I've mixed in some server-side CF and client-side JS in there but if something like this was supported, it should work. Probably would require some intensive parsing.
Instead, what I have to do now is very undesirable:
<cfinput spry:if="{ds_CurrentRowID} < 0" value="#DateFormat(today,'m/d/yyyy')#" .. />
<cfinput spry:if="{ds_CurrentRowID} >= 0" value="{dtmcontactdate}" .. />
Basically I need another tag for each condition which replicates a lot of stuff like the name, id, size, maxlength cfinput attributes.
BL: You got me. You should post this to the Spy forums.
Harin, I may be crazy, but why do you have check for current row < 0? That doesn't seem possible.
On initial load of the page, I'd like this date cfinput to default to the current date. Maybe there's a better way to do this?
I have this in the beginning of the cfm page:
<cfparam name="form.warrantyRowID" default="-1">
Then later on:
var obs = new Object;
obs.onPostLoad = function(notifier, data) {
var current_row = <cfoutput>#form.warrantyRowID#</cfoutput>
// Affects spry:detailregion below after a data load
dsWarranties.setCurrentRow(current_row);
};
dsWarranties.addObserver(obs);
I'm confused. If yo just want a form field to default to the current date, then you just do
<input type="text" name="goober" value="#dateFormat(now())#">
The cfinput in question is also inside of a spry:detailregion, which I want to change according to the master region row clicked on. When the page loads initially, I don't want Spry to automatically select the details of the first row like it normally does, but rather, I'd like the cfinput controls in the details region to be mostly blank. For that particular date cfinput, I'd like it to default to the current date.
One of the things I like about Spry is its master/detail data relationships and many of our interfaces lend themselves nicely to that structure.
I'm sorry, I'm not sure if I'm making any sense. Basically, I want Spry to control my input values after the page has loaded using region/detailregion. Initially, I want them to be blank except for this particular date input. Most of the examples I've seen of detailregion 's have to do with dumping text on the page, not with input or select tags. So maybe this is just a bad idea in general.
Here's another checkbox example of what I have do with spry conditionals, maybe this makes more sense:
<input spry:if="'{ysnresolved}' == '1'"
type="checkbox"
id="ysnresolved"
name="ysnresolved"
onclick="populateResDate();"
style="background-color: white; border:none;"
checked="true" />
<input spry:if="'{ysnresolved}' != '1'"
type="checkbox"
id="ysnresolved"
name="ysnresolved"
onclick="populateResDate();"
style="background-color: white; border:none;" />
So you can use Spry with form fields, I've done it with select boxes. Still though I'm not quite sure I get you. You want dynamic input boxes and the values come from Spry, is that right so far?
Ray, maybe if you show an example using your spry blog interface where you default one of the select boxes to something other than the first choice in the select drop down, on initial page load.
I think that's the concept he's getting at. No?
For example, take:
http://www.cflib.org/spry/i... ..
and show how you can do something like this
http://www.cflib.org/spry/i...
and what that should do is make the drop down default to dateLib selected and show the all dateLib functions.
this is not word for word what he's asking for but i think he's just asking how do i set a default value for a user input field. do i use a "spry:if" or do i use cf directly in my <input>?
Hmm. So is the default server or client side? What logic determines what your default values will be?
server-side logic.
Yeah I was using server-side logic for the default values since Spry automatically selects the first row of your xml dataset for the detailregion. For example, in your http://www.cflib.org/spry/i... example, instead of having the details of the execute function shown to me right away when I select UtilityLib, I'd like it to be blank (or something else) until I click on Execute row.
I thought about inserting a "dummy" row in my xml dataset as my first row so the detailregion defaults to this row, but I'm not sure that's the best solution either.
So to make this simpler, your question could be:
If using a detail region, how do I make it NOT auto-set to row 1 when the data is loaded.
Would that be it?
Sure ;>
So, I don't know. :) I posted to the Spry forums:
http://www.adobe.com/cfusio...
You don't have to monitor that thread though, when I hear back I'll post.
I had a few ideas as you will see in that thread. You could simply hide the detail region until someone clicks.
Thank you!
Right now, I'm setting the currentRow to -1 onPostLoad, and using Spry conditionals to default to a different value for certain form input's.
Hiding the entire detail region I'm not sure would be best in my situation as I'd like to allow users to add new records using a (mostly) blank form.
I'd still like to see what I mentioned with the cflib example.. default the library drop down to something other than the first or last selection, on initial page load.
Consider this:
Based on a user controlled setting (ex: client.libraryDefault), a user has a preset library that makes the page default to on initial load.
BL, you wouldn't use client vars, but could use a cookie. What you would do is detect when the Spry data loads, use JS to read the cookie, and then set the variable. Would be simple.
If folks like - let me whip up an example where I use cookies to store stuff like that in the CFLib example, so that, in theory, you could close browser, return, and all settings remain.
Yes, anything to show how (on initial page load) you default a drop down and it's associated dynamic region to something based on server side logic/var.
That's really what I'm getting at.
Check out
http://www.adobe.com/cfusio...
Neato. dougsm has developed some nice "add-on" features to Spry that Adobe should incorporate! I was just looking for a total-row-count property for my xml dataset too. Thanks for looking into this so much, Ray/BL.
By the way, as much as I love the master/detail region relationships that Spry offers, I've decided to remove my detail region completely and instead handle it another way. With only 3 rows in my xml dataset, initially loading 10 form input/select 's in the detail region was starting to get unacceptably slow.
What I did instead is pass the ds_RowNumber of the row clicked on to a Javascript function which loops through all the input/select/hidden form elements and sets their values using the dsWarranties.getData()[rowid]["Column Name"] notation. What makes this work nicely in my case is that my form names are exactly the same as the node names in the xml dataset. So I had elem[i].value = dsWarranties.getData()[rowid][elem[i].name] inside the loop.
This also allowed me to set the initial (default) form values on the server side as well.
Harin, sounds interesting. Maybe you can share your code with a working example?
I solved my own problem with the double sort, and double sort orders. I had to modify one word in the SpryData.js file.
By the way, the Spry js code is very well written. It's a thing of beauty. Some of the cleanest js code I've ever seen.
BL, be _sure_ to post your fix to the forums so the Spry team knows.
Nobody ever responded to my post, so screw them. Okay, okay, just kidding. I'll post something.
Ray, quick question on your rss feed. I can't email you (for some reason i always get a bounce back) so I'll post it here.
Is there a way to do something like what your doing with the MXNA feed. The sortBy=mostRecentEntry thing.
But I would like to have the ability to sort by "most recent response" and it can either return a list of entries or a list of responses (and maybe even a parameter for the count of how many to return).
Let me know if that makes sense.
If the XML data has it, then you can sort by anything. So if my RSS feed had a <lastcomment> type field, you could sort by that.
11
Do you guys know how to count the values within an XML node via Spry? And more in depth, how to count the values within that node.
For example, I have a node called "test". The possible values are "lorem1", "lorem2", and "lorem3". I have a bunch of data I'm displaying, but at the bottom of the table display, I want to display:
- The total number of "test" nodes.
- The total number of "test" nodes with value "lorem1"
- The total number of "test" nodes with value "lorem2"
- The total number of "test" nodes with value "lorem3"
I need to set a spry variable I think, but I'm not sure how to do that. Something to act as a counter of some sort.
Any suggestions?
Thanks much.
I know you can get the total Dataset length easily enough. It is jsvarname.getDat().length I believe. My code for this as at home. You would use JavaScript to manually write this out, and would need to do it on the onLoad event for the DS obviously.
There _may_ be a {ds_*} variable for it though. I need to write a quick blog post as a reference to what ds_ variables exist.
FYI - watch this space soon for a new Proof of Concept CF/Spry mashup.
Yep - ds_RowCount.
Hmm .. So I would think something like this (but it doesn't work):
var dsEmployees = new Spry.Data.XMLDataSet("data/theList.xml", "/employees/employee");
var employeeCount = dsEmployees.length;
alert(employeeCount);
Or am I missing something?
Thanks for the help thus far also.
Ed - Spry loads the data asynch. You need to use the onLoad observer (ie, tell Spry to run a function when the data is loaded.) I don't think it is onLoad, but onPostLoad. Check the docs though as I had to do this last night. (The code is back home, sorry I can't share it.)
Will do, thanks. I'll take a look. I'll continue reading here as well for more Spry info.
Thanks.
Hi Raymond I am looking for a solution about onload function for spry detail region. the first row of spry-xml-dataset is displaying in spry region and detail region when page loads intially. But on page loading i dont want to dispay any thing in DetailRegion (later if cliked on spry region item then only related item has to be displayed in DetailRegion.)
can please help me how can i achieve this.
Tannk you.
This help?
http://www.coldfusionjedi.c...
Hi ray, Thank you very much for quick reply.
1. I am able hide detail region with CSS but it couldn't display item when i clicked on spry:region ietm. Iam getting "console is undefined" java script error.
2. My requirement is not to hide detail region when the page is loading, i nedd to add some static text when it loads.
1) The console messages are debug things sent to Firebug. You can delete them.
2) Ah, well, for that, you would need a bit more code. I'd maybe just add a new div:
<div id="temp">Please wait</div>
In the JS code that shows the dregion div, hide the temp dir.
Thanks Ray. I will try that.
Hi Ray its working 99%, i strucked with small problem here.
i have two functions to call on onclick;
onclick="callToActionscript('{@src} {@add}') && showit()";
Each function is working fine individually with onclick.
please can u tell me how can i call two javascript functions with onclick. i tried like below but only one function is working.
onclick="return(callToActionscript('{@src} {@add}') && showit());"
Thank you Ray.
Hi Ray, My problem is solved just because of you.
You understood it and gave me the answer in single attempt .
Iam thanking you very much. and all the best for your rest of things.
Byeeee RAY.
@venkat: You are welcome.
Hi Ray, My problem is very similar to the one that Venkat has asked you in the previous post. I am trying to call a javascript function with the values coming back and displayed in a spry tag.
<a href="..." onclick="addrow({ID});"> linkhere </a>
I am getting an error on IE but works absolutely fine on FF. Please help.
Thank you.
To be honest, I strongly recommend not using Spry anymore. It isn't being updated.
As it stands - I kinda remember this, but not how it was fixed for IE in Spry. That doesn't help you I guess. Sorry.
I got it.. Its onclick="addnewrow('{ID}');"
Well as a part of editing old code that has spry i was asking you these questions. Personally, i feel its hard to debug code in spry.
Thanks Ray.
Sorry if I sounded like I was trying to push you away. We all have old code we have to deal with. :)