I have an object with multiple properties viz propA, propB propC and propD. I want to write a condition with OR checking more than one parameter like below.
{#if cond="'{obj.propA}'.length > 0
|| '{obj.propB}'.length > 0 || '{obj.propC}'.length> 0}
...
{/if}
Now since #if is deprecated in dust, how do i write an equivalent of this with eq or select. Or is there a new helper i can utilize for such scenarios.
I'm assuming that the props you're testing are strings.
This example requires dustjs-helpers >= 1.6.
You can use the {#any} and {#none} helpers mentioned by #rragan like this:
{#select}
{#ne key=obj.propA value="" /}
{#ne key=obj.propB value="" /}
{#ne key=obj.propC value="" /}
{#any}At least one of the above tests was true. At least one prop is not an empty string.{/any}
{#none}None of the tests above passed. All the props are empty{/none}
{/select}
select was recently extended with #any and #none that let you do multiple OR logic. Note that the .length only works because the deprecated #if uses eval. Dust tests use existence/non-existence so I think you can avoid using .length.
If you still prefer #if, see https://github.com/rragan/dust-motes/tree/master/src/helpers/control/if for an interpretive version of it that does not use eval.
Related
I'm trying to write a test in Geb that has a bunch of different text fields. The scenario is essentially that there are five or six html inputs and the user should only be allowed to type in one of them at a time. That is, if the first textbox has a value, the rest of the boxes should be immutable.
Instead of the element having an input type="disabled", they have an attribute (I'm assuming it's an attribute?) of readonly.
Here is a generic example:
<input aria-labelledby="Date Input Value 1" id="Date Input 1" name="Date Input 1" class="input-small DateOrEmpty dateInput" value="" style="display: inline-block;" readonly="">
I've tried
${"input", id: "Date Input 1"}.#readonly
as well as
${"input", id: "Date Input 1"}.has("readonly")
and I haven't had much luck..
Instead of having to deal with the fact that even an empty readonly attribute will cause the element to be read only but $("input[id='Date Input 1']").#readonly evaluates to a falsey value (as #readonly returns the value of the attribute which is an empty string in your case) why not turn the navigator into an instance of FormElement module and use the isReadOnly() property method it provides?
$("input[id='Date Input 1']").module(FormElement).readOnly
EDIT
As pointed out by kriegaex, $("input[id='Date Input 1']").#readonly actually evaluates to a truthy value (because WebDriver always returns a string which contains true when obtaining the value of readonly attribute as long as the attribute is defined on the element and regardless of the actual value of that attribute).
The above means that:
$("input[id='Date Input 1']").module(FormElement).readOnly
and:
$("input[id='Date Input 1']").#readonly
are equivalent in that they evaluate to a truthy value.
You have several problems here:
You use HTML IDs with inline spaces. This are actually not legal names and make it more difficult to write simple CSS selectors like #my-id for them.
Geb syntax for selectors uses parentheses, not curly braces. Curly braces are used for closures, which are a completely different kind of beast.
Please note that according to HTML specification the readonly attribute is boolean and always true if it exists at all, i.e. usually you do not write readonly="something" but just readonly. Even if you write readonly="false" it will evaluate to true because its value is ignored, only its existence is checked.
So if you have this HTML code:
<input id="Date Input 1" readonly>
<input id="Date Input 2">
<input id="date-input-3" readonly="false">
<input id="date-input-4">
<input id="date-input-5" readonly="">
You can write these selectors in your Geb test (please note how not using spaces in IDs makes the selectors simpler):
$("input[id='Date Input 1']").#readonly
!$("input[id='Date Input 2']").#readonly
$("input#date-input-3").#readonly
!$("input#date-input-4").#readonly
$("input#date-input-5").#readonly
select(id="xxx", name="xxxyyy")
- for(var i = 1;i<10;i++){
option(value="#{i}") Some value for #{i}
- }
but it generates the following HTML
<select id="xxxx" name "xxxyyy"></select>
<option value="1">Some value for 1</option>
....
I've tried to include the select inside the for loop and it works as expected (it generates 10 select drop controls with one item on each one of them).
What am I missing here?
I think you've got your indentation messed up. Jade is like coffeescript, in that indentation is significant and donates nesting. See here. So that the Jade engine knows that your option loop should be within the select tag, the option loop needs to be indented from the select statement, whereas you've got yours level with the select statement.
select(id="xxx", name="xxxyyy")
-for(var i = 1;i<10;i++){
option(value="#{i}") Some value for #{i}
-}
This is another problem I am facing while migrating from antlr3 to antlr4. This problem is with the java action code for handling conditional components of rules. One example is shown below.
The following grammar+code worked in antlr3. Here, if the unary operator is not present, then a value of '0' is returned, and the java code checks for this value and takes appropriate action.
exprUnary returns [Expr e]
: (unaryOp)? e1=exprAtom
{if($unaryOp.i==0) $e = $e1.e;
else $e = new ExprUnary($unaryOp.i, $e1.e);
}
;
unaryOp returns [int i]
: '-' {$i = 1;}
| '~' {$i = 2;}
;
In antlr4, this code results in a null pointer exception during a run, because 'unaryOp' is 'null' if it is not present. But if I change the code like below, then antlr generation itself reports an error:
if($unaryOp==null) ...
java org.antlr.v4.Tool try.g4
error(67): missing attribute access on rule reference 'unaryOp' in '$unaryOp'
How should the action be coded for antlr4?
Another example of this situation is in if-then-[else] - here $s2 is null in antlr4:
ifStmt returns [Stmt s]
: 'if' '(' e=cond ')' s1=stmt ('else' s2=stmt)?
{$s = new StmtIf($e.e, $s1.s, $s2.s);}
;
NOTE: question 16392152 provides a solution to this question with listeners, but I am not using listeners, my requirement is for this to be handled in the action code.
There are at least two potential ways to correct this:
The "ANTLR 4" way to do it is to create a listener or visitor instead of placing the Java code inside of actions embedded in the grammar itself. This is the only way I would even consider solving the problem in my own grammars.
If you still use an embedded action, the most efficient way to check if the item exists or not is to access the ctx property, e.g. $unaryOp.ctx. This property resolves to the UnaryOpContext you were assuming would be accessible by $unaryOp by itself.
ANTLR expects you access an attribute. Try its text attribute instead: $unaryOp.text==null
I am creating an application where the site menu would be dynamically loaded from JSON file. Each menu may correspond to an action that would be defined inside the ng-click directive. This would look something like this
<li ng-repeat="menuItem in menuContainer.menus" class="{{menuItem.cssClass}}">
<a href="{{menuItem.url}}" ng-click="{{menuItem.clickAction}}">
<i class="{{menuItem.iconClass}}"></i>{{menuItem.name}}
<span class="badge">{{menuItem.subMenus.length}}</span>
</a>`enter code here`
<li>
Now the problem is ng-click does not recognize the clickAction as a function, I believe this is due to linking process. I want to know is there any way to evaluate a string to method. I tried do $eval but it executes the function on load.
How do I do this?
Define methods not as strings, but as functions and replace ng-click="{{menuItem.clickAction}}" to ng-click="menuItem.clickAction()". Another way to define function on $scope, like:
$scope.executeString = function(body){
eval(body);
};
and replace your ng-click to ng-click="executeString(menuItem.clickAction)". Anyway, use eval is antipattern;)
Remember, that ng-click and other directives, like that, takes angular expression as parameter. And if body of you expression is a = b + c than angular convert it in javascript like $scope.a = $scope.b + $scope.c
I am having a little trouble figuring out how to do and's on EL expressions in Facelets.
So basically I have:
<h:outputText id="Prompt"
value="Fobar"
rendered="#{beanA.prompt == true && beanB.currentBase !=null}" />
But I keep getting:
Error Traced[line: 69] The entity name must immediately follow the '&'
in the entity reference.
Facelets is a XML based view technology. The & is a special character in XML representing the start of an entity like & which ends with the ; character. You'd need to either escape it, which is ugly:
rendered="#{beanA.prompt == true && beanB.currentBase != null}"
or to use the and keyword instead, which is preferred as to readability and maintainability:
rendered="#{beanA.prompt == true and beanB.currentBase != null}"
See also:
Java EE 6 tutorial - Operators in EL
Unrelated to the concrete problem, comparing booleans with booleans makes little sense when the expression expects a boolean outcome already. I'd get rid of == true:
rendered="#{beanA.prompt and beanB.currentBase != null}"
In addition to the answer of BalusC, use the following Java RegExp to replace && with and:
Search: (#\{[^\}]*)(&&)([^\}]*\})
Replace: $1and$3
You have run this regular expression replacement multiple times to find all occurences in case you are using >2 literals in your EL expressions. Mind to replace the leading # by $ if your EL expression syntax differs.