If Spry Do This...

This post is more than 2 years old.

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.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by BL posted on 8/2/2006 at 3:27 AM

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?

Comment 2 by Harin posted on 8/2/2006 at 5:00 AM

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.

Comment 3 by Raymond Camden posted on 8/2/2006 at 5:12 AM

BL: You got me. You should post this to the Spy forums.

Comment 4 by Raymond Camden posted on 8/2/2006 at 5:32 AM

Harin, I may be crazy, but why do you have check for current row < 0? That doesn't seem possible.

Comment 5 by Harin posted on 8/2/2006 at 4:14 PM

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);

Comment 6 by Raymond Camden posted on 8/2/2006 at 5:23 PM

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())#">

Comment 7 by Harin posted on 8/2/2006 at 5:36 PM

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.

Comment 8 by Harin posted on 8/2/2006 at 6:08 PM

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;" />

Comment 9 by Raymond Camden posted on 8/2/2006 at 10:26 PM

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?

Comment 10 by BL posted on 8/3/2006 at 1:18 AM

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?

Comment 11 by BL posted on 8/3/2006 at 1:34 AM

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>?

Comment 12 by Raymond Camden posted on 8/3/2006 at 1:53 AM

Hmm. So is the default server or client side? What logic determines what your default values will be?

Comment 13 by BL posted on 8/3/2006 at 2:05 AM

server-side logic.

Comment 14 by Harin posted on 8/3/2006 at 4:43 PM

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.

Comment 15 by Raymond Camden posted on 8/3/2006 at 5:22 PM

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?

Comment 16 by Harin posted on 8/3/2006 at 5:31 PM

Sure ;>

Comment 17 by Raymond Camden posted on 8/3/2006 at 5:45 PM

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.

Comment 18 by Harin posted on 8/3/2006 at 6:02 PM

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.

Comment 19 by BL posted on 8/3/2006 at 10:08 PM

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.

Comment 20 by Raymond Camden posted on 8/3/2006 at 10:14 PM

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.

Comment 21 by BL posted on 8/3/2006 at 10:25 PM

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.

Comment 22 by Raymond Camden posted on 8/4/2006 at 12:35 AM
Comment 23 by Harin posted on 8/4/2006 at 4:42 AM

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.

Comment 24 by BL posted on 8/5/2006 at 9:44 AM

Harin, sounds interesting. Maybe you can share your code with a working example?

Comment 25 by BL posted on 8/8/2006 at 12:14 AM

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.

Comment 26 by Raymond Camden posted on 8/8/2006 at 12:17 AM

BL, be _sure_ to post your fix to the forums so the Spry team knows.

Comment 27 by BL posted on 8/8/2006 at 1:22 AM

Nobody ever responded to my post, so screw them. Okay, okay, just kidding. I'll post something.

Comment 28 by BL posted on 8/8/2006 at 1:33 AM

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.

Comment 29 by Raymond Camden posted on 8/8/2006 at 1:52 AM

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.

Comment 30 by 11 posted on 9/20/2006 at 11:41 AM

11

Comment 31 by Ed posted on 11/1/2006 at 9:20 PM

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.

Comment 32 by Raymond Camden posted on 11/1/2006 at 9:23 PM

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.

Comment 33 by Raymond Camden posted on 11/1/2006 at 9:31 PM

Yep - ds_RowCount.

Comment 34 by Ed posted on 11/1/2006 at 9:33 PM

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.

Comment 35 by Raymond Camden posted on 11/1/2006 at 9:37 PM

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.)

Comment 36 by Ed posted on 11/1/2006 at 9:41 PM

Will do, thanks. I'll take a look. I'll continue reading here as well for more Spry info.

Thanks.

Comment 37 by venkat posted on 5/6/2009 at 2:44 AM

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.

Comment 38 by Raymond Camden posted on 5/6/2009 at 3:14 AM
Comment 39 by venkat posted on 5/6/2009 at 4:39 AM

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.

Comment 40 by Raymond Camden posted on 5/6/2009 at 4:43 AM

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.

Comment 41 by venkat posted on 5/6/2009 at 4:51 AM

Thanks Ray. I will try that.

Comment 42 by venkat posted on 5/6/2009 at 5:27 AM

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.

Comment 43 by venkat posted on 5/6/2009 at 5:48 AM

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.

Comment 44 by Raymond Camden posted on 5/6/2009 at 5:56 AM

@venkat: You are welcome.

Comment 45 by BhavM posted on 6/25/2012 at 5:35 PM

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.

Comment 46 by Raymond Camden posted on 6/25/2012 at 5:38 PM

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.

Comment 47 by BhavM posted on 6/25/2012 at 6:21 PM

I got it.. Its onclick="addnewrow('{ID}');"

Comment 48 by BhavM posted on 6/25/2012 at 6:22 PM

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.

Comment 49 by Raymond Camden posted on 6/25/2012 at 6:40 PM

Sorry if I sounded like I was trying to push you away. We all have old code we have to deal with. :)