2010
03.26

Today I came across an annoying problem involving the RegExpValidator class in Flex. In flex app for one of our projects StickyWorld, we allow users to upload images, pdfs, 3d models and most recently, reference YouTube movies inside a virtual room where people can comment on them, adding sticky notes in context. In our upload window, users can choose what type of media they want to add to the room, in the case of a YouTube video only the video id is required. To make it a bit more flexible we decided to allow the users to specify a url to a video as well as just the video id. The app needed to handle urls in several different formats, e.g.

  • http://www.youtube.com/watch?v=[videoid]
  • http://www.youtube.com/v/[videoid]
  • http://www.youtube.com/[userchannel]/[somepath]/[videoid]

Sounds like a job for a regular expression right? Since we also wanted to do some validation on the field to make sure we were given a valid YouTube video url or video id, it seemed that the RegExpValidator class was perfect for the job. However after adding the RegExpValidator in MXML I had a problem that took a good while to figure out what was wrong.

Below is the snippet of code containing the regular expression string, its use in the validator and a validation handler function, apologies for the wrapping of the regular expression, I have split it below where the main formats are separated by pipes.
[code lang=”actionscript”][Bindable]
private var youtubeRegExp:String = 
“^(?:http:\/\/(?:www\.)?youtube\.com\/watch(?:\?|#!)v=(.\{11\})(?:&.*)?
|(.\{11\})
|http:\/\/(?:www\.)?youtube\.com\/(?:v|[A-Za-z0-9#\/_\-]*)\/(.\{11\}))$”;

private function youtubeValid(ev:ValidationResultEvent):void
{
    if (ev.type == ValidationResultEvent.VALID) {
        for (var i:int = 0;
i < ev.results[0].matchedSubstrings.length; i++ ) {              if (ev.results[0].matchedSubstrings[i] != null)                   youtubeVidId = ev.results[0].matchedSubstrings[i];      }         txtName.text = youtubeVidId;         btnSubmit.enabled = txtYouTube.text.length>0;
    } else {
         btnSubmit.enabled = false;
    }
}

[/code]
The problem was, nothing was coming out as valid, not even the videoid just by itself. So wrote a test using the regular expression, creating a RegExp object using the expression and testing some urls using the exec function and it appeared to be working fine, so why not with the validator? In the end it turned out to be that the problem was down to several characters needing to be escaped. The correct expression that worked is below:
[code lang=”actionscript”]youtubeRegExp =
“^(?:http:\/\/(?:www\.)?youtube\.com\/watch(?:\\?|#!)v=(.\{11\})(?:&;.*)?
|(.\{11\})
|http:\/\/(?:www\.)?youtube\.com\/(?:v|[A-Za-z0-9#\/_\-]*)\/(.\{11\}))$”;[/code]

Since the regular expression used in RegExpValidator needs to be a String and the String is used as a bound property in MXML the curly brackets need to be be preceded with a backslash, because without them in MXML it means a data binding. That didn’t make much sense to me, since I was binding a String variable which contained the expression, but ok, I can kind of see the problem. What made even less sense was that I needed to double escape the ? when I actually wanted to include a literal ? in the expression. So I suppose since it is a string and I want to include the backslash character before the question mark I need to escape the backslash itself, leaving \\?, but then shouldn’t I have to do that for all the other times I need to include a backslash in the expression? Well it turns out the answer is no, I do not really understand it and only figured this out after a lot of debugging.

Another pitfall to avoid, if you are binding on a condition in MXML and you need to use logical operators, you will need to encode the logical AND && should be &amp;&amp;, the less than < should be &lt; or greater than signs > should be &gt;, logical OR || works fine. However in those cases you should really be binding to a function which returns the boolean result you are looking for.

Working with MXML is cool because you can create data-bindable UI components quickly and easily, but it really isn’t when you have to worry about silly issues like wondering why your regular expressions are not working.

3 comments so far

Add Your Comment
  1. VERY nice catch. I was stumped for hours on why my regexes wouldn’t work and this was exactly the problem. thank you.

  2. Glad it helped, I actually got stung with this again writing a valid URL regular expression, complete with optional query string and deep linking. I will create a post for it soon.

  3. […] to be required for Flex, using a single backslash does not work, read more about that in this older post. This also contains what would be capturing brackets in other languages, I could have used […]