How to make Hybris CMSParagraphComponent print variable value - sap-commerce-cloud

Is there a way to make CMSParagraphComponent print variable values?
On my controller I have something like this:
model.addAttribute("isInvoiceAvailable", currentBaseStore.isAccountPaymentAvailable());
return ControllerConstants.Views.Pages.Account.PAYMENT_OPTIONS_LANDING_PAGE;
My jsp look like this:
<cms:pageSlot position="Section1" var="feature">
<c:set var="adjustPosition" value="${true}" />
<cms:component component="${feature}" element="div" class="span-24 section1Template7 cms_disp-img_slot"/>
</cms:pageSlot>
The above mentioned component is a CMSParagraphComponent.
The CMSParagraphComponent content look like this:
UPDATE CMSParagraphComponent ; $contentCV[unique=true] ; uid[unique=true] ; content[lang=$lang]
; ; paymentOptionsParagraph ; "
<h3>Payment Options</h3>
<br>
${isInvoiceAvailable}
$isInvoiceAvailable
<h4>Credit card</h4>
<br>
<p>
MasterCard, Visa
</p>"
And when the page loads it's printing the content as if there were no variables, like this:
Is there a way to make the component print some variable value from the page contenxt?

CMSParagraphComponent is rendered using CMSParagraphComponentRenderer.java, so the Expression Language is not available at the moment of the rendering, and as a result, what you are trying to do is not possible.
I think for your use case a JSPIncludeComponent is more appropriate, another solution would be to create your own component type and use a JSP file to render it.

Related

Find if text exist inside a nested Div, if yes print out the whole string, Selenium Python

i'm very new to selenium(3.141.0) and python3, and i got a problem that couldn't figure it out.
The html looks similar to this
<div class='a'>
<div>
<p><b>ABC</b></p>
<p><b>ABC#123</b></p>
<p><b>XYZ</b></p>
<div>
</div>
I want selenium to find if # exist inside that div, (can not target the paragraph only element because sometime the text i want to extract is inside different element BUT it's always inside that <div class='a'>) If # exist => print the whole <p><b>ABC#123</b></p> (or sometime <div>ABC#123<div> )
To find an element with contained text, you must use an XPath. From what you are describing, it looks like you want the locator
//div[#class='a']//*[contains(text(),'#')]
^ a DIV with class 'a'
^ that has a descendant element that contains the text '#' within itself or a descendant
The code would look something like
for e in driver.find_elements(By.XPATH, "//div[#class='a']//*[contains(text(),'#')]"):
print(e.get_attribute('outerHTML')
and it will print all instances of <b>ABC#123</b>, <div>ABC#123</div>, or <p>ABC#123</p>, whichever exists

Checking for readonly in Geb

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

Angular JS ng-click action function as string

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

changing the font color in a computed field using javascript

How to change the font color of Hello alone in "Hello World" using javascript/some other method?
I tried the following code,
var s= session.getCommonUserName()
s.fontcolor("green")
"Hello"+" "+ s.toUpperCase()
where i tried to change just the color of the username alone. But it failed.
I wouldn't bother to send down unformatted HTML to the client and then let the client do the JavaScript work. You create a computed field and give it the data type HTML (that keeps HTML you create intact) and use SSJS. So no JS needs to execute at the client side:
var cu = session.getCommonUserName();
return "Hello"+" <span style=\"color : green\">"+ cu.toUpperCase()+"</span>";
Don't forget to cross your t, dot your i and finish a statement with a semicolon :-)
If you want to do it with client java script, then you must do something like this:
dojo.style("html_element_id", "color", "green");
So in your case you can have have something like:
<p><span id="span1">Hello</span> World.</p>
Or you can do it directly if you don't need to change it with CJS:
<p><span style="color:green">Hello</span> World</p>
one way to do it is to wrap your 'hello' in a html span and then change the color of that span.
<span id='myspan'>hello</span> world
javascript code:
document.getElementById('myspan').style.color='green';
Went old school on this one...
Say you want to put your formatted text in a div
<div id="test">
</div>
Then you need the following javascript to do so:
div = document.getElementById("test");
hello = document.createElement("span");
hello.innerHTML = "Hello"
hello.style.color = "green";
div.appendChild(hello);
div.appendChild(document.createTextNode(" world!"));

Better way to ucfirst in a Jade template?

Is there a better way to capitalize the first character of a string in Jade than this?
for list in project.lists
- list.name = list.name.charAt(0).toUpperCase() + list.name.slice(1);
li #{list.name}
Doing this every time I want to capitalize a variable is ugly, is there any way in Jade that I can define a custom function that I have available in every template like:
for list in project.lists
li #{ucfirst(list.name)}
Thanks in advance!
The contents of #{} are executed as standard JS, so you can pass in helper functions for use with things like that. You haven't specified, but assuming you are using Jade along with Express, you can do something like this:
app.locals.ucfirst = function(value){
return value.charAt(0).toUpperCase() + value.slice(1);
};
That will expose a function called ucfirst within the Jade template. You could also pass it in as part of locals every time you render, but if you are using Express it will do it automatically.
If you're willing to resort to CSS, you can create a class that capitalizes the first letter of every word within the target element.
CSS
.caps {
text-transform: capitalize;
}
Jade
div.caps
each foo in ['one', 'two', 'three']
span #{foo}
Resulting HTML
<div class="caps"><span>one</span><span>two</span><span>three</span>
Resulting view
One Two Three
If you are using pug with gulp, this can be helpful:
mixin ucfirst(text)
- text = text.charAt(0).toUpperCase() + text.slice(1);
.
#{text}
Simply call this as any other mixin:
li
+ucfirst(list.name)

Resources