ui:repeat: Regardless of validation error inner component keeps in state "valid" - el

I would like to mark a single component within ui:repeat as not valid. My attempt:
Bean:
#Named
#RequestScoped
public class TestBean {
private List<String> strLst;
#PostConstruct
public void init() {
strLst = Arrays.asList("a", "b", "c");
}
public String send() {
return null;
}
public List<String> getStrLst() {
return strLst;
}
}
Validator:
#FacesValidator(value = "TestValidator", managed = true)
public class TestValidator implements Validator<String> {
#Override
public void validate(FacesContext arg0, UIComponent comp, String foo) throws ValidatorException {
throw new ValidatorException(new FacesMessage("Error"));
}
}
Facelet:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form>
<h:messages />
<!-- After validation error component keeps in state 'valid' - wrong! -->
<ui:repeat var="str" value="#{testBean.strLst}">
<h:inputText value="#{str}" validator="TestValidator"
styleClass="#{component.valid ? 'foo' : 'error'}" />
</ui:repeat>
<!-- After validation error the component switches in state 'not valid' - correct! -->
<h:dataTable var="str" value="#{testBean.strLst}">
<h:column>
<h:inputText value="#{str}" validator="TestValidator"
styleClass="#{component.valid ? 'foo' : 'error'}" />
</h:column>
</h:dataTable>
<h:commandButton action="#{testBean.send}" value="Send" />
</h:form>
</h:body>
</html>
My problem: The component in ui:repeat keeps in state valid, so the styleClass error is not set. With h:dataTable no such problems. But I need a horizontal list, so h:dataTable is not an option here.
Also not working with Omnifaces 1.14.1 as described in https://stackoverflow.com/a/9195360/802058:
<ui:repeat var="str" value="#{testBean.strLst}">
<h:inputText value="#{str}" styleClass="#{component.valid ? 'foo' : 'error'}">
<o:validator validatorId="TestValidator" />
</h:inputText>
</ui:repeat>
Is this a bug or a feature?
Mojarra 2.3.9.SP01

Related

Could not set or bind model property with Bootstrap Datepicker in Blazor

I am using bootstrap datepicker and the problem is that when I pick a date, it does not fire a change or input event and noting is binding with the model property Course.StartDate or Course.EndDate.
The default datepicker works but does not support Afghanistan datetime. That is why I use boostrap datepicker.
Blazor code:
#using Microsoft.AspNetCore.Mvc.Rendering
#using myproject.Data
#using Microsoft.JSInterop;
#inject myproject.Repository.CoursesRepository _coursesRepository
#inject IJSRuntime JS
<EditForm Model="#Course" OnValidSubmit="e=> { if(selectedId == 0) { addCourse(); } else { updateCourse(Course.CourseId); } }">
<div class="mb-2">
<div>#Course.StartDate</div>
<label class="col-form-label" for="StartDate">#Loc["Start Date"]<span class="text-danger fs--1">*</span>:</label>
<InputDate class="form-control" #bind-Value="Course.StartDate" #bind-Value:format="yyyy-MM-dd" id="StartDate" />
<ValidationMessage class="text-danger" For="(() => Course.StartDate)"/>
</div>
<div class="mb-2">
<label class="col-form-label" for="EndDate">#Loc["End Date"]<span class="text-danger fs--1">*</span>:</label>
<InputDate class="form-control" #bind-Value="Course.EndDate" #bind-Value:format="yyyy-MM-dd" id="EndDate"/>
<ValidationMessage class="text-danger" For="(() => Course.EndDate)"/>
</div>
</EditForm>
#code {
public CourseModel Course = new();
public string[] dates = new string[] { "#StartDate", "#EndDate" };
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
loadScripts();
}
void addCourse()
{
_coursesRepository.AddCourse(Course);
FillData();
Course = new();
var title = "Course";
Swal.Success(title : Loc[$"{title} added successfully"],toast : true);
}
// initializes the datepicker
public async Task loadScripts()
{
await JS.InvokeVoidAsync("initializeDatepicker", (object) dates);
}
}
This is script for initializing the datepickers
<script>
function initializeDatepicker(dates) {
dates.forEach((element) => {
$(element).datepicker({
onSelect: function(dateText) {
// this is not working
element.value = this.value;
/*
tried this and still not working
$(element).trigger("change");
also tried this and still not working
$(element).change();
*/
// this is working
console.log("Selected date: " + dateText + "; input's current value: " + this.value);
},
dateFormat: 'yy-mm-dd',
changeMonth: true,
changeYear: true
});
});
}
</script>
The reason for this is that the changes are made with JavaScript and so the page state does not change for Blazor, in other words, Blazor does not notice the value change at all.
To solve this problem, you must inform the Blazor component of the changes by calling a C# method inside the JavaScript function. For this, you can use the DotNet.invokeMethodAsync built-in dotnet method. As follows:
DotNet.invokeMethodAsync('ProjectAssemblyName', 'ComponentMethod', this.value.toString())
Its first argument is the assembly name of your project. The second argument is the name of the C# function that you will write in the component, and finally, the third argument is the selected date value.
The method called in C# should be as follows:
static string selectedDate;
[JSInvokable]
public static void ComponentMethod(string pdate)
{
selectedDate = pdate;
}
This method must be decorated with [JSInvokable] and must be static.
I have done the same thing for another javascript calendar in Persian language. Its codes are available in the JavaScriptPersianDatePickerBlazor repository.
You can also create a custom calendar in the form of a component so that you can use it more easily in all components in any formats that you want such as DateTime or DateTimeOffset or string and so on. There is an example of this in the AmibDatePickerBlazorComponent repository.

<html:select> with Yes/No options inside <logic:iterate> passing null to form in struts

adminpage.jsp
I am iterating the users list from map and showing it in UI. Trying to send Yes/No values selected by user for agRestricted and processing it in the approve action.
<logic:iterate name="usersDetails" id="user" indexId="index">
<td><bean:write name="user" property="agName" /></td>
<td>
<html:select property="agRestricted" name="user">
<html:option value="Yes">Yes </html:option>
<html:option value="No">No</html:option>
</html:select>
</td>
<td>
<html:button property="Approve" value="" title="Approve" onclick="adminApprove()"></html:button>
</td>
</logic:iterate>
ApproveAction.java
In the approve action I am trying to read agRestricted value sent in form on submission. but Iam getting null here. Am I doing anything wrong.
public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
RegistrationForm registrationForm = (RegistrationForm) form;
if (loggingService.isInfoEnabled()) {
loggingService.logInfo(this, "is AG Restricted", agRestricted);
} // if{}//printing null
}
RegistrationForm.java
POJO Class for setting the form variables.
public class RegistrationForm extends org.apache.struts.action.ActionForm {
private String agRestricted;
private String agName;
public String getAgRestricted() {
return agRestricted;
}
public void setAgRestricted(String agRestricted) {
if (loggingService.isInfoEnabled()) {
loggingService.logInfo(this, "is AG Restricted", agRestricted);
} // if{}//printing null
this.agRestricted = agRestricted;
}
public String getAgName() {
return agName;
}
public void setAName(String agName) {
this.agName = agName;
}
}
adminpage.js
function adminApprove() {
var newUrl2 = './adminpage.do';
document.forms[0].action = newUrl2;
document.forms[0].submit();
}
struts-config.xml
<action input="/adminApprove" name="RegistrationForm"
path="/adminpage" scope="request"
type="com.cts.assetserv.core.web.action.ApproveAction" parameter="method">
<forward name="Success" path="/adminpage.do" />
<forward name="Error" path="/adminpage.do" />
</action>

Selenium IE Page title is not working. Tried IWebDriver.Title

I asked this question last week and someone marked it as a duplicate. However the duplicate reference did not answer or give solution to my question.
I am trying to get the page title to a complicated html page. I am trying to get the 'By' locator used to find an element. This is the HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="ctl00_Head1"><title>
Smart Tracking System
</title><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" /><link rel="shortcut icon" type="image/x-icon" href="../images/desktopicon.ico" /><link href="../App_Themes/appthemes/appstyles.css" type="text/css" rel="stylesheet" /><link href="../App_Themes/appthemes/calendarstyles.css" type="text/css" rel="stylesheet" /><link href="../App_Themes/appthemes/tabsstyles.css" type="text/css" rel="stylesheet" /></head>
<body>
When I copy the xpath from Firefox source code, it says the xpath is:
/html/head/title
I am using C# code to do the validation but I keep getting "LoadableComponentException..."
This is my C# code:
public class AccountsOverviewPage : CVALoadableComponent<AccountsOverviewPage>
{
private IWebDriver _driver;
private By textlabelPageHeader = By.XPath("//head[#class='title' and text()='Smart Tracking System']");
public AccountsOverviewPage()
{
_driver = ScenarioContext.Current.Get<IWebDriver>();
}
protected override void ExecuteLoad()
{
}
protected override bool EvaluateLoadedStatus()
{
if (!CVAElements.WaitForElementOnPageLoad(_driver, textlabelPageHeader))
{
UnableToLoadMessage = "Could not load Accounts Overview page within the designated timeout period";
return false;
}
return true;
}
public bool IsAt()
{
return CVAElements.CheckElementIsVisible(_driver, textlabelPageHeader);
}
}
I have even tried doing the validation by Id, and this time I used an element Id that I am sure is there:
private By textlabelPageHeader = By.Id("ctl00_Head1");
and still the validation failed. What am I not doing?? Please any assistance will be greatly appreciated.
UPDATE
This is how I am using the Driver.Title method:
public class AccountsOverviewPage : CVALoadableComponent<AccountsOverviewPage>
{
private IWebDriver _driver;
// error happens on this line:
string textlabelPageHeader = _driver.Title;
public string TextlabelPageHeader
{
get
{
return textlabelPageHeader;
}
set
{
textlabelPageHeader = value;
}
}
public AccountsOverviewPage()
{
_driver = ScenarioContext.Current.Get<IWebDriver>();
}
protected override void ExecuteLoad()
{
}
protected override bool EvaluateLoadedStatus()
{
if (!CVAElements.WaitForElementOnPageLoad(_driver, TextlabelPageHeader))
{
UnableToLoadMessage = "Could not load Accounts Overview page within the designated timeout period";
return false;
}
return true;
}
public bool IsAt()
{
return CVAElements.CheckElementIsVisible(_driver, TextlabelPageHeader);
}
and I getting error: "A field initializer cannot reference the non-static field, method, or property" here
string textlabelPageHeader = _driver.Title;
What you're trying to access - a page title - is not a web element. It's a property of the web page itself. In Selenium, you access the page title by:
String pageTitle = _driver.getTitle();
I program in Java, so that might not be the correct syntax for C#

Switch to at Iframe in selenium java

I am new using selenium and I am trying to test a web page. This page has as iframe and for the read I need do a switch, the switch I did was:
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame));
But it does not works, maybe somebody should be help me? Here is my code. this code of my page:
public class MainPage extends BasePageObject{
#FindBy(id = "cc-sa-item-logo")
WebElement iconLogin;
private By frame = By.xpath("//iframe[#id='cms']");
public MainPage() {
PageFactory.initElements(driver, this);
waitUntilPageObjectIsLoaded();
}
#Override
public void waitUntilPageObjectIsLoaded() {
wait.until(ExpectedConditions.visibilityOf(iconLogin));
}
public boolean logOutExists() {
boolean res = true;
String parentWindow = driver.getWindowHandle();
try{ wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame));
res = iconLogin.isDisplayed();
}finally {
driver.switchTo().window(parentWindow);
}
return res;
}
and this is the code of page the test:
<iframe id="cms" class="cms" src="/app/s9cea6fcedc36dd82/p430c9b54081c966d/" onload="this.loaded = true;" name="cms">
<!DOCTYPE html>
<html lang="es-ES">
<head>
<body id="page-2281940529" class="body cc-page cc-page-index cc-indexpage j-m-flash-styles j-m-gallery-styles j-m-video-styles j-m-hr-styles j-m-header-styles j-m-text-styles j-m-emotionheader-styles j-m-htmlCode-styles j-m-rss-styles j-m-form-styles-disabled j-m-table-styles j-m-textWithImage-styles j-m-downloadDocument-styles j-m-imageSubtitle-styles j-m-flickr-styles j-m-googlemaps-styles j-m-blogSelection-styles-disabled j-m-comment-styles j-m-jimdo-styles j-m-profile-styles j-m-guestbook-styles j-m-promotion-styles j-m-twitter-styles j-m-hgrid-styles j-m-shoppingcart-styles j-m-catalog-styles j-m-product-styles-disabled j-m-facebook-styles j-m-sharebuttons-styles j-m-externalSource-styles j-m-formnew-styles-disabled j-m-callToAction-styles j-m-turbo-styles j-m-spacing-styles j-m-googleplus-styles j-m-dummy-styles j-footer-styles cc-content-parent" style="background-position: -186px 0px;">
<div class="cc-bs cc-alert-container" ng-controller="cms.common.AlertCtrl"> </div>
<div id="cc-eh" data-display="cms-only">
<div id="cc-nav" class="cc-jimdo ui-draggable" data-display="cms-only">
<script>
<div id="cc-clipboard" class="cc-clipboard-scrolled-left cc-clipboard-scrolled-right cc-clipboard-empty" data-display="cms-only" style="right: 186px; display: block;">
<div id="cc-inner" class="cc-content-parent" style="padding-right: 186px; padding-top: 0px;">
<div id="cc-sa" data-display="cms-only" style="display: block;">
<div id="cc-sa-sidebar" ng-controller="cms.sa.SidebarCtrl">
<div class="cc-sa-sidebar-group cc-sa-sidebar-group--top">
<div class="cc-sa-sidebar-logo-open clear">
<span id="cc-sa-item-logo" class="cc-sa-sidebar-logo" data-params="/app/siteadmin/upgrade/index/,true" data-action="sidebarItem"> </span>
I need find the element of span tag
The issue here is that the first thing you do, after initializing the FindBy-annotated fields, is waitUntilPageObjectIsLoaded, which is implicitly calling driver.findElement(By.id("cc-sa-item-logo")).
And here it fails, as you haven't switched to the frame yet at this point, and unfortunately PageFactory is not able to handle that.
Basically you need to wrap each and every call to a FindBy-annotated field with a switchTo().frame/switchTo().defaultContent(). Just like you did in logOutExists.
For convenience, I would model the iframe in a separate page object (class), so as to encapsulate (and automate) the switching back and forth.
public class CmsIframe extends BasePageObject implements AutoCloseable {
#FindBy(id = "cc-sa-item-logo")
WebElement iconLogin;
private By frame = By.xpath("//iframe[#id='cms']");
public CmsIframe() {
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame));
PageFactory.initElements(driver, this);
waitUntilPageObjectIsLoaded();
}
#Override
public void waitUntilPageObjectIsLoaded() {
wait.until(ExpectedConditions.visibilityOf(iconLogin));
}
public boolean logOutExists() {
return iconLogin.isDisplayed();
}
#Override
public void close() {
driver.switchTo().defaultContent();
}
}
MainPage can then be re-written as follows:
public class MainPage extends BasePageObject{
private By frame = By.xpath("//iframe[#id='cms']");
public MainPage() {
PageFactory.initElements(driver, this);
}
public boolean logOutExists() {
try (CmsIframe cmsIframe = new CmsIframe()) {
return cmsIframe.logOutExists();
} // when exiting this try block, the driver will automatically be switched back out of the iframe (as part of CmsIframe#close)
}
}
Please note that thanks to implements AutoCloseable, CmsIframe can be used in a try-with-resources Statement (java > 7 only), which sorts of automates the switching back to the default content.
PS: if you could post the stacktrace with the exception you are getting, that would help help you.
I finally solved my problem, you had reason the problem was that I find the switch in the place incorrect. the solution was:
#Override
public void waitUntilPageObjectIsLoaded() {
String parentWindow = driver.getWindowHandle();
try{
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame));
wait.until(ExpectedConditions.visibilityOf(iconLogin));
}finally {
driver.switchTo().window(parentWindow);
}
}
public boolean logOutExists() {
boolean res = true;
String parentWindow = driver.getWindowHandle();
try{
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame));
res = iconLogin.isDisplayed();
}finally {
driver.switchTo().window(parentWindow);
}
return res;
}

jsf variable lost value [duplicate]

This question already has an answer here:
#ViewScoped calls #PostConstruct on every postback request
(1 answer)
Closed 5 years ago.
I have a managed Bean called bean1.java that has a boolean var called found. The variable says if a client has been found or not.
The bean has a method validate() that goes to the DB and checks if the client exists, and sets the variable to found=true if it exists or 'false' if it doesn't.
Then I keep completing other fields in my form. Now, when I click the button save, it the method saving(). That method has to do an action if the var found is true and another action if it's false.
But the problem is when I validate the variable that has been set to true on the method validate(), now it has the value "false".
#ManagedBean
#ViewScoped //SessionScoped
public class AgregarPoliza implements Serializable{
public boolean found=false;
public void validate(){
// go to data base and validate if the client exist, when exist
// set variable true
found = true; // setFound(true); <--- i already try this way too
}
public void saving(){
//it has two actions to do but need to know the value of found
System.out.println("my var found has" + found); //this system.out shows false
if(found ==true){
//makes an action
}
else{
//makes another action
}
}
//get and set of the value found
}
You should try calling the validate method in the method saving like this.
public void validate()
{
// go to data base and validate if the client exist, when exist
// set variable true
found = true; // setFound(true); <--- i already try this way too
}
public void saving(){
this.validate();
//it has two actions to do but need to know the value of found
System.out.println("my var found has" + found); //this system.out shows false
if(found ==true){
//makes an action
}
else{
//makes another action
}
i hava use this and this is working fine now check it please now it can not lost value...
AgregarPoliza.java
package com.best.uibeansTest;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "agregarPoliza")
#SessionScoped
public class AgregarPoliza implements Serializable{
public boolean found=false;
public void validate(){
// go to data base and validate if the client exist, when exist
// set variable true
found = true; // setFound(true); <--- i already try this way too
}
public String saving(){
validate();
//it has two actions to do but need to know the value of found
System.out.println("my var found has" + found); //this system.out shows false
if(found ==true){
//makes an action
}
else{
//makes another action
}
return "test2.xhtml" ;
}
//get and set of the value found
public boolean isFound() {
return found;
}
public void setFound(boolean found) {
this.found = found;
}
//get and set of the value found
}
here i just get agregarPoliza as bean i am showing jsf code below through which i check this..
test2.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<title>JSF Tutorial!</title>
</head>
<h:body>
<h2>Result</h2>
<hr />
<h:form>
<p:commandButton value="Save" ajax="false" action="#{agregarPoliza.saving}"/>
|
found value:
#{agregarPoliza.found}
</h:form>
</h:body>
</html>
on clicking of save button found value is changed to true. try this..