#2350 closed enhancement (fixed)
dojo.string.substituteParams needs to be more flexable
Reported by: | Michael Schall | Owned by: | Adam Peller |
---|---|---|---|
Priority: | high | Milestone: | 0.9beta |
Component: | String | Version: | 0.4.1 |
Keywords: | Cc: | ||
Blocked By: | Blocking: |
Description
I would like a more flexable dojo.string.substituteParams
1) have nested properties 2) call format functions for each replacement 3) allow properties to be null and give replacement
Note: Option 2: Function signature only accepts value to be formated. Option 3: I have only given ability to have a global null replacement, not per match.
Both of these could be solved by a more complex ${propertyName:formatFunction}, but my suggestion solves my issue with being overly complex.
Example
function formatName(obj) { return obj.first + " " + obj.last; } function formatDate(val) { return judo.format.date(val); } var p = {name: {first: 'Michael', middle: null, last: 'Schall'}, address: {street: null, city: 'Clive', state: 'Iowa'}, birthDate: new Date(1975, 6, 1) }; //"Call" external functions to format alert(judo.lang.substituteParams( "${name:formatName} from ${address.state} was born on ${birthDate:formatDate}", p)); //Allow property of object to be null and supply string if null alert(judo.lang.substituteParams( "first name: ${name.first} middle name: ${name.middle} last name: ${name.last}", p, {nullStr: 'n/a'}));
New function
judo.lang.substituteParams = function (/* string */template, /* object */map, /* object */ options) { if (!options){options={}}; return template.replace(/${(w+(?:.w+)*(?::w+(?:.w+)*)?)}/g, function(match, key){ var format = key.split(":"); var value = dojo.lang.getObjPathValue(format[0], map); if (format.length > 1) { var fn = dojo.lang.getObjPathValue(format[1]); value = fn(value); } if(typeof(value) != "undefined") { if (value != null) { return value; } if (typeof(options.nullStr) != "undefined") { return options.nullStr; } } dojo.raise("Substitution not found: " + key); }); };
Also, my suggestion changes the signature for dojo.string.substituteParams. The current function will take parameters after the first and create an array out of them. I personally don't like the practice since it doesn't allow for expansion of function. Why not have the user create the array when calling?
dojo.string.substituteParams("${0} ${1}", ["test", "stuff"])
I read somewhere (sorry, lost the link) that optional parameters should be sent in as an object with named properties since JavaScript? doesn't support function overloading. I like that suggestion, so I have followed that in my suggestion.
Change History (14)
comment:1 Changed 14 years ago by
comment:2 Changed 14 years ago by
Owner: | changed from psowden to Adam Peller |
---|
I'm with you on the ${} change, but I'm not thrilled with adding so much complexity to the method...
comment:3 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:4 Changed 14 years ago by
comment:5 Changed 14 years ago by
comment:9 Changed 14 years ago by
Resolution: | fixed |
---|---|
Status: | closed → reopened |
There is a small issue with the regex in this function.
dojo.string.substitute( "<span title='${AuditInformation.EnteredBy}'>" + "${AuditInformation.EnteredBy}</span>", obj)
finds key of "AuditInformation?.EnteredBy?}'>${AuditInformation?.EnteredBy?"
The regex
/${([^s:]+)(?::(S+))?}/
needs to be
/${([^s:}]+)(?::(S+))?}/
So the capture will stop if a '}' is found.
comment:10 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
comment:11 Changed 14 years ago by
Resolution: | fixed |
---|---|
Status: | closed → reopened |
I found an issue with current regex. If a format function is specified, the same issue may occur as with the last change...
dojo.string.substitute( "<span title='${AuditInformation.EnteredBy:formatName}'>" + "${AuditInformation.EnteredBy}</span>", obj)
Will find the format function of "formatName}'>${AuditInformation?.EnteredBy?"
So the format section of the regex needs to match the key section
/${([^s:}]+)(?::(S+))?}/
becomes
/${([^s:}]+)(?::([^s:}]+))?}/g
comment:12 Changed 14 years ago by
Milestone: | 0.9M1 → 0.9beta |
---|
comment:13 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
Sorry, I also forgot to point out that I changed the %{property} syntax to ${property} since that is the way widget string replacement works. I think the widget version was added to svn long before the string version. We should have a standard way of doing this.