Showing posts with label codeless. Show all posts
Showing posts with label codeless. Show all posts

11 March 2013

codeless: temporary variables

/TECH
One of the problems I ran into in January was that the userName() function in InfoPath returns something different when used on a web form in a claims-based environment. This post will walk you through two things: creating "temporary variables" in InfoPath and sanitizing the userName() result.

Temporary variables are wonderful in programming and I missed them dearly when I started working with InfoPath. Typically I'd just make a field in some obscure part of the form and not publish it, but there was always a chance that someone with some know how could find that data. It became even more prudent when I started experimenting with a service that retrieved a list of the current user's SP security groups. So I finally searched for a solution. I don't remember who's blog I read first, but there are lots of results out there that all say the same thing: use an XML file.

It's a pretty simple and clever solution. Since data connections can either be "read" OR "write", when you change the data in a secondary connection that's a read-only connection it doesn't save the data. Hey, that's kind of like a temporary variable! Constructing the XML file is pretty simple. Here's one that I've used:
<?xml version="1.0" encoding="utf-8"?>
<currentuser>
 <username />
 <preferredname />
</currentuser>
You can't specify type--as far as I can figure out--but most of the time strings are just fine. The advantage of this system is that you can get info about the current user, store it in a field for use, but not have to worry about purging the data before saving the form. This became a huge advantage with our recent userName() debacle.

In January, we launched a new web application on our SharePoint farm that utilized single sign-on and a claims-based authentication. Two major things broke when we tried using a form: accessing web services and the userName() function returned a string I'd never seen. Normally the function would return "jdoe", but in the claims-based environment it returned "i:0#.w|domain\jdoe". This was a huge issue because a lot of our forms compare the current user to some kind of list to determine access. Changing every single rule that used userName() to some unwieldy expression was not sounding fun either. So I devised a new method.

Instead, I used a temporary field and two form load rules. Using the XML example above, I then created two rules in my form load rules.

Click here to return to my listing of "codeless" blog entries. The underlined username is referring to the field in the secondary XML resource.

Rule #1 - current user has slash
Condition: contains(xdUser:get-UserName(), "\")
Action:
  Set a field's value: username = substring-after(userName(), "\")

Rule #2 - current user no slash
Condition: not(contains(xdUser:get-UserName(), "\"))
Action:
  Set a field's value: username = userName()

Now I have a field that will always contain only the username of the current user. The disadvantage of this is where you have fields that set their default value once and used the userName() function. To overcome this problem all you have to do is add a third form load rule that I like to call "First Load".

Rule #3 - First Load
Condition: FormName is blank
Action:
  Set a field's value: FormName = concat(now(), "_", username)

And that's all there is to it. Click here to return to my listing of "codeless" blog entries.

Until next time:
Work smart. Live free.

04 January 2013

codeless: double eval

/TECH
My current job title is SharePoint Developer. However, my work is a lot more specific than that. Yes I develop for SharePoint, but more specifically I develop custom, codeless web forms using InfoPath as my primary design tool. The key here is that everything I do doesn't contain custom code but rather out-of-the-box functionality used creatively. And boy do I get creative. Over the next several blog entries I want to explore some of the codeless designs I've found, developed, and refined.

The first trick I want to talk about is one that I use a ton: the double eval. When I first started developing with InfoPath I found that there were several things I couldn't do that I could in C++. Now, I understand that InfoPath isn't a programming language, but it is based on web-technology and several web languages support. So why the hell can't I systematically grab data from a repeating field?! Well, you can. I remember looking at all the functions I could use in an expression once and when I got to eval(), I had no idea how to use it. Even the description of for using it was cryptic: "Returns a node-set containing the result of the expression for each set of elements in the context field." If you added it to the expression, you got the following template:
eval(double click to insert field, "type expression here")
Now I don't know about you but I learn much more about a function by seeing an example of it being used. I finally saw an example one day of the following expression from Infopath codeless programming (walkthrough) 2:
eval(eval(Person, 'concat(my:AccountId, "|")'), "..")
At first I couldn't figure out what was going on, but after I used it several times in different forms I figured out how the two eval() functions were working together. Let's break this down starting with the inner eval().
eval(Person, 'concat(my:AccountId, "|")')
This eval() is referencing the field Person and then using concat() on it. The trick here is that the concat() function is being run relative to where Person is located. This means that if you need to do a comparison to another field with your concat(), you need to write the xpath as if the concat was running on Person. Say you want to filter AccountId based on Department. If you were to look at the xpath for the two fields you might get something like this:
- MyFields
  - Person
    = AccountId
  = Department
You'll notice that Person and Department are parallel and AccountId is a child of Person. For our concat() above to filter AccountId using Department, it would have to be done like so:
'concat(my:AccountId[../../my:Department = "IT"], "|")'
What this does is back up twice relative to where AccountId is located and then looks for Department. It's really important to know where in the hierarchy an expression is going to run. You may have also noticed that the entire expression for the eval() is enclosed in single quotes, not double quotes. That's because the expression needs to use double quotes to function correctly, thus you change the overall encapsulation to single quotes.
eval(eval(Person, 'concat(my:AccountId, "|")'), "..")
The outer eval is easier to break down and is where the "looping" action actually occurs. The outer eval() is treating the inner eval() as the field it is working on and the ".." as the expression. The unique thing about the expression here is that it is looking for one thing: when the field has to go back or up a level in the hierarchy. As soon as that happens, the outer eval returns the results of the inner eval() that occurred on each instance of Person, in this case, a string of concatenations that results in the output of a single string of text. The output would look something like this:
jcool|cbrown|ppatty|lucyvanpelt|
This is now a really useful way to gather info into a single field for further use and/or processing. I've used it to concatenate the usernames from a SharePoint list to use in a comparison in the form for security, creating a list of approvals still needed, and even doing a sort of "group by" query on a repeating table.

Thanks to Alec Pojidaev and posting that little trick to his blog. It's come in extremely useful. Check out his blog for some other codeless solutions. Click here to return to my listing of "codeless" blog entries.

Until next time:
Work hard. Play harder.

codeless

/TECH
My current job title is SharePoint Developer. However, my work is a lot more specific than that because the I nearly exclusively develop custom, codeless web forms using InfoPath as my primary design tool. The key here is that everything I do doesn't contain custom code but rather out-of-the-box functionality used creatively. And boy do I get creative. Over the next several blog entries I want to explore some of the codeless designs I've found, developed, and refined. To keep things tidy, I'll preface each post title with "codeless" so you know what you're getting into and additionally keep links to all my "codeless" posts here. If you're working with InfoPath, I hope these articles help you.

"codeless" articles:
Until next time:
Work hard. Play harder.

18 December 2012

codeless: expression box/calculated value

/TECH
Have you ever needed to display text that changed depending on other aspects of the current form in question? If you have, perhaps you've already used these. But if you're like me and you didn't see an obvious solution (a rarity in SharePoint and Infopath) you found another way. I personally used sections and text fields to dynamically hide and display text. But this isn't the only way.

I discovered this little feature by accident one day. They're called an Expression Box in 2007 and a Calculated Value in 2010. These incredibly simple controls are part of the form template only, which means the data in them is never stored with the form itself. One disadvantage that I can tell though is that you can't reference them, much like a button control. But if you're already basing the info in the control off of data in the form, you don't need to reference it.

But the thing that bothers me the most is that I've been working with InfoPath for 2.5 years now and never knew about them. If you haven't discovered them yet, go use them cause God knows they're useful.

Until next time:
Work hard. Play harder.