Primefaces datatable, nested conditional row coloring - css

I'm using PF 3.4.1 and JSF.
I would like to have a conditional selection of the css rowclass depending on two conditions:
One style should be for objects that are disabled, and one for objects that are expired.
I was able to put this two conditions in the same time, but, obviously, this cause a redundancy of css classes. I would like to have an overwrite of the classes in order to have predominance of the css class of disabled objects on expired objects.
Should look like this structure:
if (expired){
if (disabled){
return css1;
}
return css2
}
However, that is the code:
<p:dataTable id="results" var="utente" value="#{searchController.userList}"
paginator="true" rows="10"
rowStyleClass="#{user.expDate le user.currentDate ? 'rowdatatable3' : 'rowdatatable2'} #{user.enabled eq 'FALSE' ? 'rowdatatable1' : 'rowdatatable2'}"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,25,50">
rowdatatableX are css styles.
With this code, results have always rowdatatable2 or rowdatable1 and never the 3rd option.
My idea was something like this:
rowStyleClass="#{user.expDate le user.currentDate ? #{user.enabled eq 'FALSE' ? 'rowdatatable1' : 'rowdatatable3'} : 'rowdatatable2'} "
..but it doesn't work.
Please help to find a solution. Thanks.

Try writing a method in your Bean (or transient method in user entity) that compares 2 dates expDate and currentDate
public boolean isExpired() {
return getExpDate.before(getCurrentDate);
}
If user.enabled is of type boolean skip the FALSE comparison. Since your table variable is utente you should use it! Your expression should look like that
"#{utente.expired ? (utente.enabled ? 'rowdatatable1' : 'rowdatatable3') : 'rowdatatable2'}"
so:
IF expired AND enabled -> 'rowdatatable1'
IF expired AND disabled -> 'rowdatatable3'
IF NOT expired -> 'rowdatatable2'

Related

Handlebars Using #root in Custom Helper

I have a scenario where I am trying to access a separate element in my custom helper from within a nested for loop. When I use root outside my for loop I don't have any issues, but I can't seem to use #root within my custom helper. I thought maybe ../ would work, but it appears that is only be moving up to the parent element, not a one that is separate
Here are my two objects:
category //Object being looped through
categoryQuery //Query object being compared to looped values
Here is my view (looping through ID's and then apply selected to the ID attached to categoryQuery:
{{#category}}
<option value="{{this.categoryId}}"{{selected this.categoryId #root.categoryQuery}}>{{this.categoryName}}</option>
{{/category}}
Preselected value if the values match:
/Preselect option value that is associated with edited record
hbs.registerHelper('selected', function(option, value){
if (option === value) {
return 'selected';
} else {
return '';
}
});
Updated:
when adding console.log('Option : ' + option + ' Value : ' + value); into the else statement of my registered helper, I receive the following, which shows that it isn't an issue that #root.category isn't pulling in the value, but it isn't equating correctly.
For example:
Option : 1 Value : 2
Option : 2 Value : 2
Option : 1 Value : undefined
I determined that the root cause of the issue was the strictness in the comparison operator. When changed to == I was able to correctly identify the ID's that matched

NLog Colored Console

I am using NLog to log errors. Here is the Config code
<target name="console" xsi:type="AsyncWrapper" >
<target xsi:type="ColoredConsole" layout="${longdate:padding=-10}${callsite:className=false:includeSourcePath=false:methodName=false} | ${message}" >
<highlight-row condition="level >= LogLevel.Info" foregroundColor="Green" backgroundColor="NoChange"/>
</target>
</target>
I have a custom property set on the log event like
private LogEventInfo GetLogEvent(string loggerName, LogLevel level, string message, ConsoleColor color)
{
var logEvent = new LogEventInfo(level, loggerName, message);
logEvent.Properties["color"] = color;// color= any console color
}
and this sets the "color" property.(lets say "Red" here)
and I am trying to use this "color" property in the target like
<highlight-row condition="equals('${color}','Red')" foregroundColor="Red" backgroundColor="NoChange"/>
this dosent work and I tried
<highlight-row condition="equals('${event-context:item=color}','Red')" foregroundColor="Red" backgroundColor="NoChange"/>
but no luck.
Am I missing something or is there a better way of doing this? Can we use Layout renderers in this case? If yes how do we implement this?
First, since you are storing values in LogEventInfo.Properties, you should be using your second configuration example, which gets the value from event-context.
I have not used the ColoredConsoleTarget, so take this as a suggestion, not as something that I know for a fact will work.
I suspect that the NLog Condition object does not know about the ConsoleOutputColor enum. So, when you store a ConsoleOutputColor enum value in LogEventInfo.Properties, the Condition does not know that 'Red' (in the condition) refers to ConsoleOutputColor.Red. I have two suggestions:
First option: store the string value of the ConsoleOutputColor in LogEventInfo.Properties. Using ToColor might be sufficient. Something like this:
var logEvent = new LogEventInfo(level, loggerName, message);
logEvent.Properties["color"] = color.ToString();
Then, in your Condition, you should be able to compare against the ConsoleOutputColor string values (what you have in your configuration might be right, if you store the color name string as I suggested).
If that doesn't work, you could try...
Second option: store the ConsoleOutputColor value in LogEventInfo.Properties, as you are doing now, but change your condition in the config file to compare the "color" from event-context to the numeric value of the ConsoleOutputColor values. Something like this (I have not tried this so I don't know for sure that it is correct):
<highlight-row condition="equals('${event-context:item=color}','12')" foregroundColor="Red" backgroundColor="NoChange"/>
(In the ConsoleOutputColor enum, Red is 12).

How to use ? : if statements with Razor and inline code blocks

I'm updating my old .aspx views with the new Razore view engine. I have a bunch of places where I have code like this:
<span class="vote-up<%= puzzle.UserVote == VoteType.Up ? "-selected" : "" %>">Vote Up</span>
Ideally I'd like to do this:
<span class="vote-up#{puzzle.UserVote == VoteType.Up ? "-selected" : ""}">Vote Up</span>
However there's two problems here:
vote-up#{puzzle.UserVote .... is not treating the # symbol as a start of a code block
#puzzle.UserVote == VoteType.Up looks at the first part #puzzle.UserVote as if it's supposed to render the value of the variable.
Anyone know how to address these issues?
This should work:
<span class="vote-up#(puzzle.UserVote == VoteType.Up ? "-selected" : "")">Vote Up</span>
#( condition ? "true" : "false" )
The key is to encapsulate the expression in parentheses after the # delimiter. You can make any compound expression work this way.
In most cases the solution of CD.. will work perfectly fine. However I had a bit more twisted situation:
#(String.IsNullOrEmpty(Model.MaidenName) ? " " : Model.MaidenName)
This would print me " " in my page, respectively generate the source &nbsp;. Now there is a function Html.Raw(" ") which is supposed to let you write source code, except in this constellation it throws a compiler error:
Compiler Error Message: CS0173: Type of conditional expression cannot
be determined because there is no implicit conversion between
'System.Web.IHtmlString' and 'string'
So I ended up writing a statement like the following, which is less nice but works even in my case:
#if (String.IsNullOrEmpty(Model.MaidenName)) { #Html.Raw(" ") } else { #Model.MaidenName }
Note: interesting thing is, once you are inside the curly brace, you have to restart a Razor block.

Peculiar error with ColdFusion on BlueDragon.NET

We've got an odd issue occurring with ColdFusion on BlueDragon.NET. Asking here because of the broad experience of StackOverflow users.
Tags inside POSTed content to out BlueDragon.NET server gets removed, and we're not sure where in the stack it's getting removed. So for example if we post this data
[CORE]
Lesson_Status=Incomplete
Lesson_Location=comm_13_a02_bs_enus_t17s06v01
score=
time=00:00:56
[Core_Lesson]
<sd ac="" pc="7.0" at="1289834380459" ct="" ><t id="lo8" sc=";;" st="c" /></sd>
<sd ac='' pc='7.0' at='1289834380459' ct='' ><t id='lo8' sc=';;' st='c' /></sd>
<sd ac="" pc="7.0" at="1289834380459" ct="" ><t id="lo8" sc=";;" st="c" /></sd>
<sd ac="" pc="7.0" at="1289834380459" ct="" ><t id="lo8" sc=";;" st="c" /></sd>
<b>hello1</b>
<i>hello2</i>
<table border><td>hello3</td></table>
<sd>hello4</sd>
<sd ac="1">hello5</sd>
<t>hello6</t>
<t />
<t attr="hello8" />
<strong>hello10</strong>
<img>
><>
What we get back is this:
[CORE]
Lesson_Status=Incomplete
Lesson_Location=comm_13_a02_bs_enus_t17s06v01
score=
time=00:00:56
[Core_Lesson]
hello1
hello2
hello3
hello4
hello5
hello6
hello10
>
That is, anything that starts with < and ends with > is getting stripped or filtered and no longer appears in ColdFusion's FORM scope when it's posted.
Our server with BlueDragon JX does not suffer this problem.
If we bypass using the default FORM scope and use this code, the tag-like content appears:
<cfscript>
// get the content string of the raw HTTP headers, will include all POST content as a long querystring
RAWREQUEST = GetHttpRequestData();
// split the string on "&" character, each variable should now be separate
// note that at this point duplicate variables will get clobbered
RAWFORMFIELDS = ListToArray(RAWREQUEST.content, "&");
// We're creating a structure like "FORM", but better
BetterFORM = StructNew();
// Go over each of the raw form fields, take the key
// and add it as a key, and decode the value into the value field
// and trap the whole thing if for some reason garbage gets in there
for(i=1;i LTE ArrayLen(RAWFORMFIELDS);i = i + 1) {
temp = ListToArray(RAWFORMFIELDS[i], "=");
try {
tempkey = temp[1];
tempval = URLDecode(temp[2]);
StructInsert(BetterFORM, tempkey, tempval);
} catch(Any e) {
tempThisError = "Malformed Data: " & RAWFORMFIELDS[i];
// Log the value of tempThisError here?
// WriteOutput(tempThisError);
}
}
</cfscript>
<cfdump var="#BetterFORM#">
If we do this, and use the created BetterFORM variable, it's there, so it does not seem to be a problem with the requests being filtered at some other point in the stack. I was thinking maybe it was URLScan, but that appears not to be installed. Since BD.NET runs on .NET as the engine, perhaps there's some sanitization setting that is being used on all variables somehow?
Suggestions, ideas, etc are welcome on this issue.
I don't have a BD.NET instance handy to check, but Adobe ColdFusion has a setting in the cf administrator to strip "invalid tags". That's my best guess. Adobe CF replaces them with "invalidTag", my guess is that BD.Net just strips it silently.
It turned out to be very mundane.
We had a custom tag that did customized string replacements. On one server, it was modified to NOT replace all tags. On this server, we were using an older version that did. So the fault was not a difference between BlueDragon JX and BlueDragon.NET -- it was developer team error.

How can I tell if E4X expression has a match or not?

I am trying to access an XMLList item and convert it to am XML object.
I am using this expression:
masonicXML.item.(#style_number == styleNum)
For example if there is a match everything works fine but if there is not a match then I get an error when I try cast it as XML saying that it has to be well formed. So I need to make sure that the expression gets a match before I cast it as XML. I tried setting it to an XMLList variable and checking if it as a text() propertie like this:
var defaultItem:XMLList = DataModel.instance.masonicXML.item.(#style_number == styleNum);
if(defaultItem.text())
{
DataModel.instance.selectedItem = XML(defaultItem);
}
But it still give me an error if theres no match. It works fine if there is a match.
THANKS!
In my experience, the simplest way to check for results is to grab the 0th element of the list and see if it's null.
Here is your code sample with a few tweaks. Notice that I've changed the type of defaultItem from XMLList to XML, and I'm assigning it to the 0th element of the list.
var defaultItem:XML =
DataModel.instance.masonicXML.item.(#style_number == styleNum)[0];
if( defaultItem != null )
{
DataModel.instance.selectedItem = defaultItem;
}
OK I got it to work with this:
if(String(defaultItem.#style_number).length)
Matt's null check is a good solution. (Unless there is the possibility of having null items within an XMLList.. probably not, but I haven't verified this.)
You can also check for the length of the XMLList without casting it to a String:
if (defaultItem.#style_number.length() > 0)
The difference to String and Array is that with an XMLList, length() is a method instead of a property.

Resources