Added comma separated on the foreach Velocity loop - velocity

What should I added to the following foreach loop (Velocity codes) to get the final result like appNames=A,B,C
#if($approval.has())
#foreach($item in $approval.rejected)
#set($appNames =$item.appName)
#end
#end
Thanks

I'd suggest using $foreach.hasNext for a cleaner code:
#if($approval.has())
#foreach($item in $approval.rejected)
#set($appNames =$item.appName)
#if( $foreach.hasNext ),#end
#end
#end

Just simply do add separator to it in the loop and String concatenation
#if($approval.has())
#set($appNames ="")
#set($separator="")
#foreach($item in $approval.rejected)
#set($appNames =$appNames +$separator +$item.appName)
#set($separator = ",")
#end
#end
appNames= $appNames
output
appNames= A,B,C

Related

How to skip duplicate values in the apache velocity js

I want to skip the duplicate values so using below code but it seems not working.
#set($uniqueEntities=[])
#foreach($e in $entities)
#if($foreach.index <=12)
#if($uniqueEntities != ($e.offerId))
#set($uniqueEntities=$e.offerId)
#end
$uniqueEntities,
#set($foreach.index = $foreach.index + 1)
#end
#end
Response :
OFF-56938,OFF-44046,OFF-27626,OFF-60503,OFF-49318,OFF-52824,1355738,OFF-13099,OFF-27626,OFF-11757,1355717,OFF-27305,OFF-42752
I do not want OFF-27626 to reappear. How could we fix this please?
Without actually knowing velocity.js, looking at this answer I think this might work for you
#set($uniqueEntities = [])
#foreach($e in $entities)
#if( ! $uniqueEntities.contains( $e.offerId ) )
#if( $uniqueEntities.add($e.offerId) ) #end
##note the if above is to trap a "true" return - may not be required
$e.offerId
#end
#end

How do I make a macro that calls a block with arbitrary arguments? [duplicate]

In my code i have a lot of code like:
if (block) block(....)
So I want to define a macro, something like
#define safetyCall(block, ...) if((block)) {block(##__VA_ARGS__)};
But i couldn't get it to work. Any idea?
You don't need the ## and the ; needs moving:
#define safetyCall(block, ...) if((block)) { block(__VA_ARGS__); }
This can run into issues if your block is inline and contains code that has a series of comma separated strings, etc.
Example:
safetyCall(^void() {
NSArray *foo = #[#"alice", "bob"];
};
The compiler will complain about "Expected ']' or '.'" and "Expected identifier or '('".
However, if you were to declare the inline block as a separate block before the macro, it will not generate an error.
Example:
void (^fooBlock)(void) = ^void() {
NSArray *foo = #[#"alice", #"bob"];
}
safetyCall(fooBlock);

how to pass block as a macro's argument in objective-c?

In my code i have a lot of code like:
if (block) block(....)
So I want to define a macro, something like
#define safetyCall(block, ...) if((block)) {block(##__VA_ARGS__)};
But i couldn't get it to work. Any idea?
You don't need the ## and the ; needs moving:
#define safetyCall(block, ...) if((block)) { block(__VA_ARGS__); }
This can run into issues if your block is inline and contains code that has a series of comma separated strings, etc.
Example:
safetyCall(^void() {
NSArray *foo = #[#"alice", "bob"];
};
The compiler will complain about "Expected ']' or '.'" and "Expected identifier or '('".
However, if you were to declare the inline block as a separate block before the macro, it will not generate an error.
Example:
void (^fooBlock)(void) = ^void() {
NSArray *foo = #[#"alice", #"bob"];
}
safetyCall(fooBlock);

function with multiple arguments

how to pass multiple arguments in a single function in Objective-C? I want to pass 2 integer values and the return value is also integer. I want to use the new Objective-C syntax, not the old C/C++ syntax.
In objective-c it is really super easy. Here is the way you would do it in C:
int functName(int arg1, int arg2)
{
// Do something crazy!
return someInt;
}
This still works in objective-c because of it's compatibility with C, but the objective-c way to do it is:
// Somewhere in your method declarations:
- (int)methodName:(int)arg1 withArg2:(int)arg2
{
// Do something crazy!
return someInt;
}
// To pass those arguments to the method in your program somewhere:
[objectWithOurMethod methodName:int1 withArg2:int2];
Best of luck!
Since this is still google-able and there are better solutions than the accepted answer; there's no need for the hideous withArg2 – just use colons:
Declaration:
#interface
-(void) setValues: (int)v1 : (int)v2;
Definition:
#implementation
-(void) setValues: (int)v1 : (int)v2 {
//do something with v1 and v2
}
Like this:
int sum(int a, int b) {
return a + b;
}
Called like this:
int result;
result = sum(3, 5);
// result is now 8
More here
int add (int a, int b)
{
int c;
c = a + b;
return c;
}
link text

conditional operator in Velocity

Is there a way to do ternary operators in Velocity?
This is what I'd like to do:
#set ($name = ($args.get(0) == "") ? "default" : $args.get(0))
Instead of chunky if-else
#if ($args.get(0) == "")
#set ($name = "default")
#else
#set ($name = $args.get(0))
#end
Any ideas?
From experience and reading the VTL Reference there is no way to do this. If you had lots of assignments like this maybe you could look at defining your own velocimacro to try and avoid repeating the if else.
For example, if the macro only prints a single string you could do the following:
#set ($name = "#condOpt($args.get(0), "default")")
The double quotes around the macro call are important as that means the RHS of the #set is parsed.
I ended up doing as you said, Mark:
#macro(condOp $check, $default)
#if ($check == "")
$default
#else
$check
#end
#end
And then I can call it like so:
#set ($name = "#condOp($args.get(0), 'default')")
For the record, with Velocity 2.1+, you can provide alternate reference values:
${args[0]|'default'}